/* === 911001 ============================================================ */ /* STATENS KARTVERK - FYSAK-PC */ /* Fil: fylr.c */ /* Ansvarlig: Andreas Røstad */ /* Innhold: Rutiner for geografisk søking mm. i fysak-pc */ /* ======================================================================= */ #include "stdafx.h" #include #include #include #include /* Globale variabler */ extern LC_SYSTEMADM Sys; /* --- Lokale rutiner */ static LC_R_LEAF * LR_R_Insert(long lGrNr,LC_BOKS * pB,LC_R_NODE * pFar,LC_R_NODE * pRN,LC_R_NODE * *ppNyRN); static LC_R_NODE * LR_R_CreateRNode( LC_R_NODE * pFar,short sSonType); static LC_R_LEAF * LR_R_CreateRLeaf(long lGrNr, LC_BOKS * pB,LC_R_NODE * pFar); static void LR_R_BoksSum(LC_BOKS * pB1,LC_BOKS * pB2); static double LR_BoksDeltaArealSum(LC_BOKS * pB1,LC_BOKS * pB2); static void LR_LeggTilKB(LC_GEO_STATUS * pGeoStat,LC_FILADM *pFil,long lNr); static short LR_R_BoksTestIntersect(LC_BOKS * pB1,LC_BOKS * pB2); static void LR_R_SjekkNode(LC_GEO_STATUS * pGeoStat,LC_BOKS * pB,LC_FILADM *pFil,LC_R_NODE * pRN); static void LR_R_SjekkNodeFlate(LC_GEO_STATUS * pGeoStat,LC_BOKS * pB,LC_FILADM *pFil,LC_R_NODE * pRN); static void LR_VelgMetode(LC_GEO_STATUS * pGeoStat); //#ifdef TEST //#include //static void LR_R_DumpNode(LC_R_NODE * pRN, int iNivo); static void LR_R_DumpLov(LC_R_LEAF * pRL, LC_FILADM *pDumpFil, int iNivo, double dA, double dN,long *plAntBarn); static void LR_R_DumpNode(LC_R_NODE * pRN, LC_FILADM *pDumpFil, int iNivo, double dA, double dN, double dLengde,long *plAntBarn); //#endif #define MAX_REF 25 /* AR:2000-07-25 CH LC_GetGrWin Hent omskrevet rektangel for gruppe CD ========================================================================== CD Formål: CD Henter omskrevet rektangel for gitt gruppe. CD For flater er refererte grupper medregnet. CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_BGR * pBgr i Gruppenummer CD double *nva u Omskrevet rektangel for gruppen. Avrundet utover CD double *nvn u en enhet. CD double *oha u CD double *ohn u CD short ist r Status. UT_TRUE=OK, UT_FALSE=ulovlig gruppenummer. CD CD Bruk: CD ist = LC_GetGrWin(&Bgr,&nva,&nvn,&oha,&ohn); ========================================================================== */ SK_EntPnt_FYBA short LC_GetGrWin(LC_BGR * pBgr,double *nva,double *nvn,double *oha,double *ohn) { LC_R_LEAF * pRL; /* LO_TestFilpeker(pBgr->pFil,"LC_GetGrWin"); */ LO_TestFilpeker(pBgr->pFil,"GetGrWin"); /* Lovlig gruppe */ if (pBgr->lNr >= 0L && pBgr->lNr < pBgr->pFil->lAntGr) { pRL = LI_GetGeo(pBgr->pFil,pBgr->lNr); if (pRL != NULL) { *nva = pRL->Boks.dMinAust; *nvn = pRL->Boks.dMinNord; *oha = pRL->Boks.dMaxAust; *ohn = pRL->Boks.dMaxNord; } else { *nva = *nvn = (double)LONG_MAX; *oha = *ohn = (double)LONG_MIN; } return UT_TRUE; /* ======> */ } /* Ulovlig gruppe */ LC_Error(36,"(LC_GetGrWin)",""); return UT_FALSE; } /* AR-930608 CH LR_Indx Beregn geografiske ruter for gruppe CD ========================================================================== CD Formål: CD Beregner og lagrer omskrevet boks for koordinatene på aktuell gruppe. CD CD Parametre: ingen CD CD Bruk: CD LR_Indx(); ========================================================================== */ void LR_Indx(void) { short sfeil; long pt; double min_n,min_a,max_n,max_a; double radius,aust,nord,fi,dfi; LC_BOKS Boks; // UT_FPRINTF(stderr,"Indeks for: %s\n",LX_GetGi(1)); /* Bygg ny indeks */ if (Sys.pGrInfo->nko > 0) { /* Nullstill omskreven boks */ min_a = min_n = (double)LONG_MAX; max_a = max_n = (double)LONG_MIN; /* Handterer "bue" */ if (Sys.pGrInfo->gnavn == L_BUE || Sys.pGrInfo->gnavn == L_BUEP || Sys.pGrInfo->gnavn == L_SIRKEL || Sys.pGrInfo->gnavn == L_SIRKELP) { if (LC_GetBuePar(HENT_FORRFRA,&aust,&nord,&radius,&fi,&dfi,&sfeil)) { /* Beregner omskrevet rektangel for "buen" */ GM_buebox(aust,nord,radius,fi,dfi,&min_a,&min_n,&max_a,&max_n); } else { if (Sys.pGrInfo->gnavn == L_BUE) { /* Ulovlig bue-angivelse */ //LC_Error(130,"(LR_Indx)",LX_GetGi(1)); UT_FPRINTF(stderr,"Ulovlig forhold mellom koordinater og radius i: %s : %s\n",Sys.GrId.pFil->pszNavn,LX_GetGi(1)); } // Spesialhandtering av ulogiske sirkler og buer. Håndteres som KURVE for (pt=0; ptnko; pt++) { min_a = fymin(min_a,*(Sys.pdAust + pt)); min_n = fymin(min_n,*(Sys.pdNord + pt)); max_a = fymax(max_a,*(Sys.pdAust + pt)); max_n = fymax(max_n,*(Sys.pdNord + pt)); } } /* Andre grupper enn "bue" */ } else { /* Omskreven firkant */ for (pt=0; ptnko; pt++) { min_a = fymin(min_a,*(Sys.pdAust + pt)); min_n = fymin(min_n,*(Sys.pdNord + pt)); max_a = fymax(max_a,*(Sys.pdAust + pt)); max_n = fymax(max_n,*(Sys.pdNord + pt)); } } /* Beregn omskreven boks */ /* Nedre venstre justeres ut en enhet */ Boks.dMinAust = min_a - Sys.pGrInfo->dEnhet; Boks.dMinNord = min_n - Sys.pGrInfo->dEnhet; /* Øvre høyre justeres ut en enhet */ Boks.dMaxAust = max_a + Sys.pGrInfo->dEnhet; Boks.dMaxNord = max_n + Sys.pGrInfo->dEnhet; // Finnes ikke i treet fra før if (Sys.pGrInfo->pRL == NULL ) { /* Lagre omskrevet boks i søketreet */ Sys.pGrInfo->pRL = LR_InsertGeo(Sys.GrId.pFil,Sys.GrId.lNr,&Boks); // Sjekk om boksen avviker fra gammel boks } else if (memcmp(&(Sys.pGrInfo->pRL->Boks),&Boks,sizeof(LC_BOKS)) != 0) { /* Fjern eventuell gammel forekomst i R-treet */ LR_R_Delete(Sys.pGrInfo->pRL); /* Lagre omskreven firkant i søketreet */ Sys.pGrInfo->pRL = LR_InsertGeo(Sys.GrId.pFil,Sys.GrId.lNr,&Boks); } } else if (Sys.pGrInfo->pRL != NULL) { /* Fjern eventuell gammel forekomst i R-treet */ LR_R_Delete(Sys.pGrInfo->pRL); Sys.pGrInfo->pRL = NULL; } } // ========================================================================== SK_EntPnt_FYBA void LC_DumpGeoRtre(LC_FILADM *pFil) { short ostat; LC_FILADM *pDumpFil; long lAntBarn = 0; // Åpner ny SOSI-fil for dump HO_New("Indeksdump.sos", 99, 0.0, 0.0, 0.001, 0.001, 0.001, -151000, -151000, 151000, 1000); if (LC_OpenSos("Indeksdump.sos",LC_BASE_FRAMGR,LC_NY_IDX,LC_INGEN_STATUS,&pDumpFil,&ostat)) { short sUtvidModus = LC_GetUtvidModus(); long lMaxSkriv = LC_InqMaxSkriv(); LC_SetUtvidModus(LC_UTVID_RASK); LC_MaxSkriv(100000000L); if (pFil->pGeoRN != NULL) { LR_R_DumpNode(pFil->pGeoRN,pDumpFil,0, 0.0, 0.0, 100000.0,&lAntBarn); } LC_MaxSkriv(lMaxSkriv); LC_Save(); LC_SetUtvidModus(sUtvidModus); LC_CloseSos(pDumpFil,SAVE_IDX); } } // ========================================================================== static void LR_R_DumpNode(LC_R_NODE * pRN, LC_FILADM *pDumpFil, int iNivo, double dA, double dN, double dLengde,long *plAntBarn) { LC_BGR Bgr; char szTx[100]; int i; long lSnr; double dDeltaN; long lBarn = 0; iNivo++; /* Rekursiv sjekk av de underliggende løv eller nodene */ for (i=0; isSonAnt; i++) { LC_NyGr(pDumpFil,".LINJE",&Bgr,&lSnr); LC_PutGi(LC_AppGiL(), "..LTEMA 1000"); LC_PutTK(LC_AppKoL(), dA, dN); dDeltaN = dLengde; if (i == 0) { LC_PutTK(LC_AppKoL(), dA-dLengde, dN-dDeltaN); LC_WxGr(SKRIV_OPTIMALT); if (pRN->sSonType == LC_LEAF) { LR_R_DumpLov(pRN->Son.pLeaf[i], pDumpFil, iNivo, dA-dLengde, dN-dDeltaN, &lBarn); } else { LR_R_DumpNode(pRN->Son.pNode[i], pDumpFil, iNivo, dA-dLengde, dN-dDeltaN, dLengde / 3.1, &lBarn); } } else if (i == 1) { LC_PutTK(LC_AppKoL(), dA, dN-dDeltaN); LC_WxGr(SKRIV_OPTIMALT); if (pRN->sSonType == LC_LEAF) { LR_R_DumpLov(pRN->Son.pLeaf[i], pDumpFil, iNivo, dA, dN-dDeltaN, &lBarn); } else { LR_R_DumpNode(pRN->Son.pNode[i], pDumpFil, iNivo, dA, dN-dDeltaN, dLengde / 3.1, &lBarn); } } else { LC_PutTK(LC_AppKoL(), dA+dLengde, dN-dDeltaN); LC_WxGr(SKRIV_OPTIMALT); if (pRN->sSonType == LC_LEAF) { LR_R_DumpLov(pRN->Son.pLeaf[i], pDumpFil, iNivo, dA+dLengde, dN-dDeltaN, &lBarn); } else { LR_R_DumpNode(pRN->Son.pNode[i], pDumpFil, iNivo, dA+dLengde, dN-dDeltaN, dLengde / 3.1, &lBarn); } } } // Skriv ut noden LC_NyGr(pDumpFil,".PUNKT",&Bgr,&lSnr); LC_PutGi(LC_AppGiL(), "..PTEMA 3000"); LC_PutGi(LC_AppGiL(), "..NODE 1"); UT_SNPRINTF(szTx,100,"..NIVÅ %d", iNivo-1); LC_PutGi(LC_AppGiL(), szTx); UT_SNPRINTF(szTx,100,"..MIN-NØ %f %f", pRN->Boks.dMinNord, pRN->Boks.dMinAust); LC_PutGi(LC_AppGiL(), szTx); UT_SNPRINTF(szTx,100,"..MAX-NØ %f %lf", pRN->Boks.dMaxNord, pRN->Boks.dMaxAust); LC_PutGi(LC_AppGiL(), szTx); UT_SNPRINTF(szTx,100,"..DELTA-NØ %f %f", pRN->Boks.dMaxNord - pRN->Boks.dMinNord, pRN->Boks.dMaxAust - pRN->Boks.dMinAust); LC_PutGi(LC_AppGiL(), szTx); UT_SNPRINTF(szTx,100,"..BARN %ld",lBarn); LC_PutGi(LC_AppGiL(), szTx); LC_PutTK(LC_AppKoL(), dA, dN); LC_WxGr(SKRIV_OPTIMALT); (*plAntBarn) += lBarn; } // ========================================================================== static void LR_R_DumpLov(LC_R_LEAF * pRL, LC_FILADM *pDumpFil, int iNivo, double dA, double dN, long *plAntBarn) { LC_BGR Bgr; char szTx[100]; long lSnr; (*plAntBarn)++; // Skriv ut løvet LC_NyGr(pDumpFil,".PUNKT",&Bgr,&lSnr); LC_PutGi(LC_AppGiL(), "..PTEMA 5000"); LC_PutGi(LC_AppGiL(), "..LØV 1"); UT_SNPRINTF(szTx,100,"..NR %ld", pRL->lNr); LC_PutGi(LC_AppGiL(), szTx); UT_SNPRINTF(szTx,100,"..NIVÅ %d", iNivo); LC_PutGi(LC_AppGiL(), szTx); UT_SNPRINTF(szTx,100,"..MIN-NØ %f %f", pRL->Boks.dMinNord, pRL->Boks.dMinAust); LC_PutGi(LC_AppGiL(), szTx); UT_SNPRINTF(szTx,100,"..MAX-NØ %f %f", pRL->Boks.dMaxNord, pRL->Boks.dMaxAust); LC_PutGi(LC_AppGiL(), szTx); UT_SNPRINTF(szTx,100,"..DELTA-NØ %f %f", pRL->Boks.dMaxNord - pRL->Boks.dMinNord, pRL->Boks.dMaxAust - pRL->Boks.dMinAust); LC_PutGi(LC_AppGiL(), szTx); LC_PutTK(LC_AppKoL(), dA, dN); LC_WxGr(SKRIV_OPTIMALT); } /* AR-900214 CH LR_IndxFlate Beregn geografisk indeks for flate CD ============================================================================= CD Formål: CD Utvider omskrevet boks for aktuell gruppe, slik at den tar hensyn til CD referanser. CD CD Parametre: ingen CD CD Bruk: CD LR_IndxFlate(); ============================================================================= */ void LR_IndxFlate(void) { long ref_arr[MAX_REF]; unsigned char ref_status[MAX_REF]; long ant_ref; short s,ngi; long nko; unsigned short info; double min_n,min_a,max_n,max_a; LC_R_LEAF * pRL; LC_FILADM *pFi = Sys.GrId.pFil; LC_GRF_STATUS GrfStat; LC_BOKS Boks; short sRefBrukt = UT_FALSE; LC_GetGrPara(&ngi,&nko,&info); /* Sjekk om gruppen har referanser */ if ((info & GI_REF) != 0 || nko >0) { /* Nullstill omskreven boks */ min_a = min_n = (double)LONG_MAX; max_a = max_n = (double)LONG_MIN; /* Koordinater direkte på denne gruppen */ if (nko > 0) { pRL = LI_GetGeo(pFi,Sys.GrId.lNr); if (pRL != NULL) { min_a = pRL->Boks.dMinAust; min_n = pRL->Boks.dMinNord; max_a = pRL->Boks.dMaxAust; max_n = pRL->Boks.dMaxNord; } else { /* Initier med inverse område fra filhodet */ min_a = Sys.GrId.pFil->Omraade.dMaxAust; min_n = Sys.GrId.pFil->Omraade.dMaxNord; max_a = Sys.GrId.pFil->Omraade.dMinAust; max_n = Sys.GrId.pFil->Omraade.dMinNord; } } else { /* Initier med inverse område fra filhodet */ min_a = Sys.GrId.pFil->Omraade.dMaxAust; min_n = Sys.GrId.pFil->Omraade.dMaxNord; max_a = Sys.GrId.pFil->Omraade.dMinAust; max_n = Sys.GrId.pFil->Omraade.dMinNord; } LC_InitGetRefFlate(&GrfStat); /* * Bygger opp omskreven firkant for gruppen ut fra omskreven * firkant for gruppene som inngår. * (Behandle bare ytre avgrensing.) */ ant_ref = LC_GetRefFlate(&GrfStat,GRF_YTRE,ref_arr,ref_status,MAX_REF); do { for (s=0; sBoks.dMinAust); min_n = fymin(min_n, pRL->Boks.dMinNord); max_a = fymax(max_a, pRL->Boks.dMaxAust); max_n = fymax(max_n, pRL->Boks.dMaxNord); } } if (ant_ref > 0) sRefBrukt = UT_TRUE; if (ant_ref < MAX_REF) break; ant_ref = LC_GetRefFlate(&GrfStat,GRF_YTRE,ref_arr,ref_status,MAX_REF); } while (ant_ref > 0); /* Lagre omskreven firkant i søketreet */ Boks.dMinAust = min_a; Boks.dMinNord = min_n; Boks.dMaxAust = max_a; Boks.dMaxNord = max_n; /* Fjern eventuell representasjonspunktet fra R-treet */ if (Sys.pGrInfo->pRL != NULL) LR_R_Delete(Sys.pGrInfo->pRL); /* Legger inn hele flaten */ Sys.pGrInfo->pRL = LR_InsertGeo(Sys.GrId.pFil,Sys.GrId.lNr,&Boks); } /* Husk om referanser er brukt */ if (sRefBrukt == UT_TRUE) { LI_SetBt(pFi,Sys.GrId.lNr,BT_REFBOX); } else { LI_ClrBt(pFi,Sys.GrId.lNr,BT_REFBOX); } } /* AR-911003 CH LC_SBGeo Sett søkegrense for grov geografisk søk CD ============================================================================= CD Formål: CD Definerer geografisk område for geografisk søk. CD CD Parametre: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat iu Peker til struktur for søkestatus. CD unsigned short usLag i Velg hvilke "lag" det skal søkes i. CD LC_FRAMGR og /eller LC_BAKGR CD double nv_a i Koordinat nedre venstre hjørne. CD double nv_n i CD double oh_a i Koordinat øvre høyre hjørne. CD double oh_n i CD CD Bruk: CD LC_GEO_STATUS GeoStat; CD . CD LC_SBGeo(&GeoStat,LC_FRAMGR | LC_BAKGR,nv_a,nv_n,oh_a,oh_n); CD if (LC_FFGeo(&GeoStat,&Bgr)) { CD do{ CD . Behandle funnet gruppe CD . CD } while (LC_FNGeo(&GeoStat,&bgr)); CD } CD LC_AvsluttSok(&GeoStat); CD . ============================================================================= */ SK_EntPnt_FYBA void LC_SBGeo(LC_GEO_STATUS * pGeoStat,unsigned short usLag, double nv_a,double nv_n,double oh_a,double oh_n) { /* Normaliserer vinduet */ GM_NormVindu(&nv_a,&nv_n,&oh_a,&oh_n); /* Avrunder ut til nærmeste meter utover */ /* Nedre venstre ut til nærneste heltall under */ //pGeoStat->nvn = (long)floor(nv_n); //pGeoStat->nva = (long)floor(nv_a); /* Øvre høyre ut til nærneste heltall over */ //pGeoStat->ohn = (long)ceil(oh_n); //pGeoStat->oha = (long)ceil(oh_a); pGeoStat->nvn = nv_n; pGeoStat->nva = nv_a; pGeoStat->ohn = oh_n; pGeoStat->oha = oh_a; /* Husk lag */ pGeoStat->usLag = usLag; /* Nullstiller resultatpekerne */ pGeoStat->pForsteKB = NULL; pGeoStat->pSisteKB = NULL; pGeoStat->pAktuellKB = NULL; /* Velg søkemetode */ LR_VelgMetode(pGeoStat); } /* AR-911003 CH LC_FFGeo Finn første ved geografisk søk CD ========================================================================== CD Formål: CD Finner første gruppe i det definerte området for kombinert geografisk søk. CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat iu Peker til struktur for søkestatus CD LC_BGR * pBgr u Funnet gruppe CD short sstat r Søkestatus (UT_TRUE=Funnet, UT_FALSE=Ingen funnet) CD CD Bruk: CD Se under LC_SBGeo. ========================================================================== */ SK_EntPnt_FYBA short LC_FFGeo(LC_GEO_STATUS * pGeoStat,LC_BGR * pBgr) { /* Bruker R-tre */ if (pGeoStat->usMetode == LC_GEO_RTRE) { LC_BOKS Boks; LC_FILADM *pFil; /* Beregn søkeboksen */ Boks.dMinAust = pGeoStat->nva; Boks.dMinNord = pGeoStat->nvn; Boks.dMaxAust = pGeoStat->oha; Boks.dMaxNord = pGeoStat->ohn; /* Frigir eventuell gammel resultatkjede */ LC_AvsluttSok(pGeoStat); /* Sjekker alle filer */ LC_InitNextFil(&pFil); while (LC_NextFil(&pFil,pGeoStat->usLag)) { /* Filen inneholder data, må sjekke alle berørte noder */ if (pFil->pGeoRN != NULL) { LR_R_SjekkNode(pGeoStat,&Boks,pFil,pFil->pGeoRN); } } pGeoStat->pAktuellKB = pGeoStat->pForsteKB; if (pGeoStat->pAktuellKB != NULL) { /* Tilslag */ *pBgr = pGeoStat->pAktuellKB->Bgr; return UT_TRUE; } /* Sekvensiell gjennomgang av alle grupper */ } else { LC_BGR Bgr; LC_R_LEAF * pRL; LC_InitNextBgr(&Bgr); while (LC_NextBgr(&Bgr,pGeoStat->usLag)) { pRL = LI_GetGeo(Bgr.pFil,Bgr.lNr); if (pRL != NULL) { /* Sjekk område-tabellen */ if (pGeoStat->ohn >= pRL->Boks.dMinNord && pGeoStat->oha >= pRL->Boks.dMinAust && pGeoStat->nvn <= pRL->Boks.dMaxNord && pGeoStat->nva <= pRL->Boks.dMaxAust) { *pBgr = pGeoStat->Bgr = Bgr; /* Tilslag */ return UT_TRUE; } } } /* Ikke tilslag */ pGeoStat->Bgr = Bgr; } /* Ikke tilslag */ return UT_FALSE; } /* AR-911003 CH LR_R_SjekkNode Sjekker node om overlappende boks CD ========================================================================== CD Formål: CD Sjekker en node og underliggende noder om de har lagret bokser CD som overlapper søkerektanglet. De gruppene som blir funnet blir hengt på CD kjeden med søkeresultat i pGeoStat. CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat i Peker til struktur for søkestatus CD LC_BOKS * pB i Søkeboks CD LC_FILADM * pFil i Filpeker CD LC_R_NODE * pRN i Peker til node som skal sjekkes CD CD Bruk: CD LR_R_SjekkNode(pGeoStat,pB,pFil,pRN->pSon[i]); ========================================================================== */ static void LR_R_SjekkNode(LC_GEO_STATUS * pGeoStat,LC_BOKS * pB,LC_FILADM *pFil,LC_R_NODE * pRN) { int i; /* Sjekk om denne noden berører søkeboksen */ if (LR_R_BoksTestIntersect(&(pRN->Boks),pB)) { /* Har kommet til ytterste nivå */ if (pRN->sSonType == LC_LEAF) { /* Sjekk de gruppene som er lagret under denne noden */ for (i=0; isSonAnt; i++) { if (LR_R_BoksTestIntersect(&(pRN->Son.pLeaf[i]->Boks),pB)) { LR_LeggTilKB(pGeoStat,pFil,pRN->Son.pLeaf[i]->lNr); } } /* Node */ } else { /* Rekursiv sjekk av de underliggende nodene */ for (i=0; isSonAnt; i++) { LR_R_SjekkNode(pGeoStat,pB,pFil,pRN->Son.pNode[i]); } } } } /* AR-911003 CH LR_R_BoksTestIntersect Sjekker om to bokser "berører" hverandre CD ========================================================================== CD Formål: CD Sjekker om to bokser "berører" hverandre. CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_BOKS * pB1 i Rektangel 1 CD LC_BOKS * pB2 i Rektangel 2 CD short sStatus r UT_TRUE=Berører, UT_FALSE=Ikke berøring CD CD Bruk: CD LR_R_BoksTestIntersect(...); ========================================================================== */ static short LR_R_BoksTestIntersect(LC_BOKS * pB1,LC_BOKS * pB2) { if (pB1->dMaxNord >= pB2->dMinNord && pB1->dMaxAust >= pB2->dMinAust && pB1->dMinNord <= pB2->dMaxNord && pB1->dMinAust <= pB2->dMaxAust ) { /* Tilslag */ return UT_TRUE; } return UT_FALSE; } /* AR-911003 CH LC_FNGeo Finn neste ved geografisk søk CD ========================================================================== CD Formål: CD Finner neste gruppe i det definerte området for geografisk søk. CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat iu Peker til struktur for søkestatus CD LC_BGR * pBgr u Funnet gruppe CD short sstat r Søkestatus (UT_TRUE=Funnet, UT_FALSE=Ingen funnet) CD CD Bruk: CD Se under LC_SBGeo. ========================================================================== */ SK_EntPnt_FYBA short LC_FNGeo(LC_GEO_STATUS * pGeoStat,LC_BGR * pBgr) { /* Bruker R-tre */ if (pGeoStat->usMetode == LC_GEO_RTRE) { /* Søket er utført og ligger som en kjede */ if (pGeoStat->pAktuellKB != NULL) { pGeoStat->pAktuellKB = pGeoStat->pAktuellKB->pNesteKB; if (pGeoStat->pAktuellKB != NULL) { /* Tilslag */ *pBgr = pGeoStat->pAktuellKB->Bgr; return UT_TRUE; } } /* Sekvensiell gjennomgang av alle grupper */ } else { LC_R_LEAF * pRL; LC_BGR Bgr = pGeoStat->Bgr; while (LC_NextBgr(&Bgr,pGeoStat->usLag)) { pRL = LI_GetGeo(Bgr.pFil,Bgr.lNr); if (pRL != NULL) { /* Sjekk område-tabellen */ if (pGeoStat->ohn >= pRL->Boks.dMinNord && pGeoStat->oha >= pRL->Boks.dMinAust && pGeoStat->nvn <= pRL->Boks.dMaxNord && pGeoStat->nva <= pRL->Boks.dMaxAust) { *pBgr = pGeoStat->Bgr = Bgr; /* Tilslag */ return UT_TRUE; } } } /* Ikke tilslag */ pGeoStat->Bgr = Bgr; } /* Ikke tilslag */ return UT_FALSE; } /* AR-911003 CH LC_FFGeoFil Finn første ved geografisk søk i en fil CD ========================================================================== CD Formål: CD Finner første gruppe i det definerte området for kombinert geografisk søk. CD Søker bare i en gitt fil. CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat iu Peker til struktur for søkestatus CD LC_FILADM * pOnsketFil i Filpeker til den filen det skal søkes i. CD LC_BGR * pBgr u Funnet gruppe CD short sstat r Søkestatus (UT_TRUE=Funnet, UT_FALSE=Ingen funnet) CD CD Bruk: CD Se under LC_SBGeo. ========================================================================== */ SK_EntPnt_FYBA short LC_FFGeoFil(LC_GEO_STATUS * pGeoStat,LC_FILADM *pOnsketFil,LC_BGR * pBgr) { /* Bruker R-tre */ if (pGeoStat->usMetode == LC_GEO_RTRE) { LC_BOKS Boks; /* Beregn søkeboksen */ Boks.dMinAust = pGeoStat->nva; Boks.dMinNord = pGeoStat->nvn; Boks.dMaxAust = pGeoStat->oha; Boks.dMaxNord = pGeoStat->ohn; /* Frigir eventuell gammel resultatkjede */ LC_AvsluttSok(pGeoStat); /* Sjekker den aktuelle filen */ if (pOnsketFil->usLag & pGeoStat->usLag) { /* File inneholder data, må sjekke alle berørte noder */ if (pOnsketFil->pGeoRN != NULL) { LR_R_SjekkNode(pGeoStat,&Boks,pOnsketFil,pOnsketFil->pGeoRN); } } pGeoStat->pAktuellKB = pGeoStat->pForsteKB; if (pGeoStat->pAktuellKB != NULL) { /* Tilslag */ *pBgr = pGeoStat->pAktuellKB->Bgr; return UT_TRUE; } /* Sekvensiell gjennomgang av alle grupper */ } else { LC_BGR Bgr; LC_R_LEAF * pRL; LC_InitNextBgr(&Bgr); while (LC_NextBgr(&Bgr,pGeoStat->usLag)) { /* Rett fil? */ if (Bgr.pFil == pOnsketFil) { pRL = LI_GetGeo(Bgr.pFil,Bgr.lNr); if (pRL != NULL) { /* Sjekk område-tabellen */ if (pGeoStat->ohn >= pRL->Boks.dMinNord && pGeoStat->oha >= pRL->Boks.dMinAust && pGeoStat->nvn <= pRL->Boks.dMaxNord && pGeoStat->nva <= pRL->Boks.dMaxAust) { *pBgr = pGeoStat->Bgr = Bgr; /* Tilslag */ return UT_TRUE; } } } } /* Ikke tilslag */ pGeoStat->Bgr = Bgr; } /* Ikke tilslag */ return UT_FALSE; } /* AR-911003 CH LC_FNGeoFil Finn neste ved geografisk søk i en fil CD ========================================================================== CD Formål: CD Finner neste gruppe i det definerte området for geografisk søk. CD Søker bare i en gitt fil. CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat iu Peker til struktur for søkestatus CD LC_FILADM * pFil i Filpeker til den filen det skal søkes i. CD LC_BGR * pBgr u Funnet gruppe CD short sstat r Søkestatus (UT_TRUE=Funnet, UT_FALSE=Ingen funnet) CD CD Bruk: CD Se under LC_SBGeo. ========================================================================== */ SK_EntPnt_FYBA short LC_FNGeoFil(LC_GEO_STATUS * pGeoStat,LC_FILADM *pFil,LC_BGR * pBgr) { /* Bruker R-tre */ if (pGeoStat->usMetode == LC_GEO_RTRE) { if (pGeoStat->pAktuellKB != NULL) { pGeoStat->pAktuellKB = pGeoStat->pAktuellKB->pNesteKB; if (pGeoStat->pAktuellKB != NULL) { /* Tilslag */ *pBgr = pGeoStat->pAktuellKB->Bgr; return UT_TRUE; } } /* Sekvensiell gjennomgang av alle grupper */ } else { LC_R_LEAF * pRL; LC_BGR Bgr = pGeoStat->Bgr; while (LC_NextBgr(&Bgr,pGeoStat->usLag)) { if (Bgr.pFil == pFil) { pRL = LI_GetGeo(Bgr.pFil,Bgr.lNr); if (pRL != NULL) { /* Sjekk område-tabellen */ if (pGeoStat->ohn >= pRL->Boks.dMinNord && pGeoStat->oha >= pRL->Boks.dMinAust && pGeoStat->nvn <= pRL->Boks.dMaxNord && pGeoStat->nva <= pRL->Boks.dMaxAust) { *pBgr = pGeoStat->Bgr = Bgr; /* Tilslag */ return UT_TRUE; } } } } /* Ikke tilslag */ pGeoStat->Bgr = Bgr; } /* Ikke tilslag */ return UT_FALSE; } /* AR-911002 CH LC_FAGeo Finn alle ved geografisk søk CD ========================================================================== CD Formål: CD Finn alle i geografisk søkeområde. CD Tilslag merkes i brukttabellen kolonne BT_GEOSOK (15). CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat iu Peker til struktur for søkestatus CD long lAntall r Antall funnet. CD CD Bruk: CD . CD LC_SBGeo(&GeoStat,LC_FRAMGR | LC_BAKGR,nv_a,nv_n,oh_a,oh_n); CD antall = LC_FAGeo(&Bgr); CD . ============================================================================= */ SK_EntPnt_FYBA long LC_FAGeo(LC_GEO_STATUS * pGeoStat) { short ngi; long nko; unsigned short info; LC_BGR AktBgr,Bgr; long lAntall = 0; /* Husk aktuell gruppe */ AktBgr = Sys.GrId; /* Blanker brukttabellen */ LI_EraseBt(BT_GEOSOK,BT_GEOSOK); /* Utfører søket */ if (LC_FFGeo(pGeoStat,&Bgr)) { do { LC_RxGr(&Bgr,LES_OPTIMALT,&ngi,&nko,&info); lAntall += LC_MerkGr(BT_GEOSOK,1); /* Tilslag */ } while (LC_FNGeo(pGeoStat,&Bgr)); } LC_AvsluttSok(pGeoStat); /* Les tilbake aktuell gruppe */ if (AktBgr.lNr != INGEN_GRUPPE) { LC_RxGr(&AktBgr,LES_OPTIMALT,&ngi,&nko,&info); } return lAntall; } /* AR-911003 CH LC_SBFlate Sett søkegrense for geografisk søk på flate CD ============================================================================= CD Formål: CD Definerer punkt for geografisk søk på flate. CD CD Parametre: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat iu Peker til struktur for søkestatus CD unsigned short usLag i Velg hvilke "lag" det skal søkes i. CD LC_FRAMGR og /eller LC_BAKGR CD double nv_a i Koordinat nedre venstre hjørne CD double nv_n i CD double oh_a i Koordinat øvre høyre hjørne CD double oh_n i CD CD Bruk: CD LC_GEO_STATUS GeoStat; CD . CD LC_SBFlate(&GeoStat,LC_FRAMGR | LC_BAKGR,nv_a,nv_n,oh_a,oh_n); CD if (LC_FFFlate(&GeoStat,&Bgr)) { CD do{ CD . Behandle funnet gruppe CD . CD } while (LC_FNFlate(&GeoStat,&Bgr)); CD } CD LC_AvsluttSok(&GeoStat); CD . ============================================================================= */ SK_EntPnt_FYBA void LC_SBFlate(LC_GEO_STATUS * pGeoStat,unsigned short usLag, double nv_a,double nv_n,double oh_a,double oh_n) { /* Normaliserer vinduet */ GM_NormVindu(&nv_a,&nv_n,&oh_a,&oh_n); /* Avrunder ut til nærmeste meter utover */ /* Nedre venstre ut til nærneste heltall under */ pGeoStat->nvn = (long)floor(nv_n); pGeoStat->nva = (long)floor(nv_a); /* Øvre høyre ut til nærneste heltall over */ pGeoStat->ohn = (long)ceil(oh_n); pGeoStat->oha = (long)ceil(oh_a); /* Husk lag */ pGeoStat->usLag = usLag; /* Nullstiller resultatpekerne */ pGeoStat->pForsteKB = NULL; pGeoStat->pSisteKB = NULL; pGeoStat->pAktuellKB = NULL; /* Velg søkemetode */ LR_VelgMetode(pGeoStat); } /* AR-911003 CH LC_FFFlate Finn første ved flatesøk CD ============================================================================= CD Formål: CD Finner første gruppe i det definerte området for flatesøk. CD CD Parametre: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat iu Peker til struktur for søkestatus CD LC_BGR * pBgr u Funnet gruppe CD short sstat r Søkestatus (UT_TRUE=Funnet, UT_FALSE=Ingen funnet) CD CD Bruk: CD Se under LC_SBFlate. ============================================================================= */ SK_EntPnt_FYBA short LC_FFFlate(LC_GEO_STATUS * pGeoStat,LC_BGR * pBgr) { /* Bruker R-tre */ if (pGeoStat->usMetode == LC_GEO_RTRE) { LC_BOKS Boks; LC_FILADM *pFil; /* Beregn søkeboksen */ Boks.dMinAust = pGeoStat->nva; Boks.dMinNord = pGeoStat->nvn; Boks.dMaxAust = pGeoStat->oha; Boks.dMaxNord = pGeoStat->ohn; /* Frigir eventuell gammel resultatkjede */ LC_AvsluttSok(pGeoStat); /* Sjekker alle filer */ LC_InitNextFil(&pFil); while (LC_NextFil(&pFil,pGeoStat->usLag)) { /* File inneholder data, må sjekke alle berørte kvadranter */ if (pFil->pGeoRN != NULL) { LR_R_SjekkNodeFlate(pGeoStat,&Boks,pFil,pFil->pGeoRN); } } pGeoStat->pAktuellKB = pGeoStat->pForsteKB; if (pGeoStat->pAktuellKB != NULL) { /* Tilslag */ *pBgr = pGeoStat->pAktuellKB->Bgr; return UT_TRUE; } /* Sekvensiell gjennomgang av alle grupper */ } else { LC_BGR Bgr; LC_R_LEAF * pRL; LC_InitNextBgr(&Bgr); while (LC_NextBgr(&Bgr,pGeoStat->usLag)) { if (LI_InqBt(Bgr.pFil,Bgr.lNr,BT_REFBOX)) { pRL = LI_GetGeo(Bgr.pFil,Bgr.lNr); if (pRL != NULL) { /* Sjekk område-tabellen */ if (pGeoStat->ohn >= pRL->Boks.dMinNord && pGeoStat->oha >= pRL->Boks.dMinAust && pGeoStat->nvn <= pRL->Boks.dMaxNord && pGeoStat->nva <= pRL->Boks.dMaxAust) { *pBgr = pGeoStat->Bgr = Bgr; /* Tilslag */ return UT_TRUE; } } } } /* Ikke tilslag */ pGeoStat->Bgr = Bgr; } /* Ikke tilslag */ return UT_FALSE; } /* AR-980205 CH LR_R_SjekkNodeFlate Sjekker node om overlappende boks (flate) CD ========================================================================== CD Formål: CD Sjekker en node og underliggende noder om de har lagret bokser CD som overlapper søkerektanglet. De gruppene som blir funnet blir hengt på CD kjeden med søkeresultat i pGeoStat. Finner bare grupper der det er brukt CD referanser for oppbygging av geografisk boks. CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat i Peker til struktur for søkestatus CD LC_BOKS * pB i Søkeboks CD LC_FILADM * pFil i Filpeker CD LC_R_NODE * pRN i Peker til node som skal sjekkes CD CD Bruk: CD LR_R_SjekkNodeFlate(pGeoStat,pB,pFil,pRN->pSon[i]); ========================================================================== */ static void LR_R_SjekkNodeFlate(LC_GEO_STATUS * pGeoStat,LC_BOKS * pB,LC_FILADM *pFil,LC_R_NODE * pRN) { int i; /* Sjekk om denne noden berører søkeboksen */ if (LR_R_BoksTestIntersect(&(pRN->Boks),pB)) { /* Har kommet til ytterste nivå */ if (pRN->sSonType == LC_LEAF) { /* Sjekk de gruppene som er lagret under denne noden */ for (i=0; isSonAnt; i++) { if (LR_R_BoksTestIntersect(&(pRN->Son.pLeaf[i]->Boks),pB)) { /* Huskes bare hvis det er brukt referanser */ if (LI_InqBt(pFil,pRN->Son.pLeaf[i]->lNr,BT_REFBOX)) { LR_LeggTilKB(pGeoStat,pFil,pRN->Son.pLeaf[i]->lNr); } } } /* Node */ } else { /* Rekursiv sjekk av de underliggende nodene */ for (i=0; isSonAnt; i++) { LR_R_SjekkNodeFlate(pGeoStat,pB,pFil,pRN->Son.pNode[i]); } } } } /* AR-911002 CH LC_FNFlate Finn neste ved flatesøk CD ========================================================================== CD Formål: CD Finner neste gruppe i det definerte området for flatesøk. CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat iu Peker til struktur for søkestatus CD LC_BGR * pBgr u Funnet gruppe CD short sstat r Søkestatus (UT_TRUE=Funnet, UT_FALSE=Ingen funnet) CD CD Bruk: CD Se under LC_SBFlate. ========================================================================== */ SK_EntPnt_FYBA short LC_FNFlate(LC_GEO_STATUS * pGeoStat,LC_BGR * pBgr) { /* Bruker R-tre */ if (pGeoStat->usMetode == LC_GEO_RTRE) { if (pGeoStat->pAktuellKB != NULL) { pGeoStat->pAktuellKB = pGeoStat->pAktuellKB->pNesteKB; if (pGeoStat->pAktuellKB != NULL) { /* Tilslag */ *pBgr = pGeoStat->pAktuellKB->Bgr; return UT_TRUE; } } /* Sekvensiell gjennomgang av alle grupper */ } else { LC_R_LEAF * pRL; LC_BGR Bgr = pGeoStat->Bgr; while (LC_NextBgr(&Bgr,pGeoStat->usLag)) { if (LI_InqBt(Bgr.pFil,Bgr.lNr,BT_REFBOX)) { pRL = LI_GetGeo(Bgr.pFil,Bgr.lNr); if (pRL != NULL) { /* Sjekk område-tabellen */ if (pGeoStat->ohn >= pRL->Boks.dMinNord && pGeoStat->oha >= pRL->Boks.dMinAust && pGeoStat->nvn <= pRL->Boks.dMaxNord && pGeoStat->nva <= pRL->Boks.dMaxAust) { *pBgr = pGeoStat->Bgr = Bgr; /* Tilslag */ return UT_TRUE; } } } } /* Ikke tilslag */ pGeoStat->Bgr = Bgr; } /* Ikke tilslag */ return UT_FALSE; } /* AR-890824 CH LC_WTst Vindustest CD ========================================================================== CD Formål: CD Sjekk om aktuell gruppe berører gitt vindu. CD Tar hensyn til gruppenavnet. Handterer (PUNKT, LINJE, KURVE, BUE, CD BUEP, SIRKEL, SIRKELP, SVERM, TRASE ). CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD double nva i Avgrensing av vinduet CD double nvn i CD double oha i CD double ohn i CD short ist r status: 0 = ikke berøring CD 1 = skjæring CD CD Bruk: CD . CD LC_SBGeo(&GeoStat,nv_a,nv_n,oh_a,oh_n); CD if (LC_FFGeo(&GeoStat,&Bgr)){ CD do{ CD LC_RxGr(&Bgr,LES_OPTIMALT,&ngi,&nko,&info); CD if (LC_WTst(nv_a,nv_n,oh_a,oh_n)) { (Nøyaktig vindustest) CD . Behandle funnet gruppe CD . CD } CD } while (LC_FNGeo(&GeoStat,&Bgr)); CD } CD LC_AvsluttSok(&GeoStat); CD . ========================================================================== */ SK_EntPnt_FYBA short LC_WTst(double nva,double nvn,double oha,double ohn) { short ngi,gruppenavn,sfeil; long nko,pt; unsigned short info; double radius,aust,nord,fi,dfi; double *pdAust = Sys.pdAust; double *pdNord = Sys.pdNord; if (Sys.GrId.lNr != INGEN_GRUPPE) { /* Har aktuell gruppe */ gruppenavn = LC_GetGrPara(&ngi,&nko,&info); if (nko > 0){ /* Har koordinater */ /* .BUE, .BUEP, .SIRKEL eller .SIRKELP */ if (gruppenavn == L_BUE || gruppenavn == L_BUEP || gruppenavn == L_SIRKEL || gruppenavn == L_SIRKELP) { if (LC_GetBuePar(HENT_FORRFRA,&aust,&nord,&radius,&fi,&dfi,&sfeil)) { /* Vindustest på buen */ if (GM_wtstBue(aust,nord,radius,fi,dfi,nva,nvn,oha,ohn)) { return(1); } } else { // Spesialhandtering av ulogiske sirkler og buer // Handteres som punkt/linje // Sjekk første koordinat if (GM_wtst(*pdAust,*pdNord,*pdAust,*pdNord,nva,nvn,oha,ohn)) { return(1); } // Sjekk resten av gruppen ++pdAust; ++pdNord; for (pt=1; ptnko; ++pt,++pdAust,++pdNord) { if (GM_wtst(*(pdAust-1),*(pdNord-1),*pdAust,*pdNord, nva,nvn,oha,ohn)) { return(1); } } } /* .PUNKT eller .SVERM */ } else if (gruppenavn == L_PUNKT || gruppenavn == L_SVERM) { /* Sjekk om noe punkt er innenfor */ for (pt=1; pt<=Sys.pGrInfo->nko; ++pt) { LC_GetTK(pt,&aust,&nord); if (aust >= nva && aust <= oha && nord >= nvn && nord <= ohn ) { return(1); } } /* .TRASE */ } else if (gruppenavn == L_TRASE) { short ngi; long nko; unsigned short info; LC_POLYGON Polygon; LC_POL_ELEMENT * pPE; LC_BGR BgrTrase = Sys.GrId; /* Husk gruppenummer for traseen */ /* Initier referansehandtering, og les beskrivelsen */ LC_POL_InitPolygon(&Polygon); LC_POL_GetRef(&Polygon); /* Behandle referansene */ for (pPE = Polygon.HovedPO.pForstePE; pPE != NULL; pPE = pPE->pNestePE) { LC_RxGr(&pPE->Bgr,LES_OPTIMALT,&ngi,&nko,&info); if (LC_WTst(nva,nvn,oha,ohn)) { /* (Nøyaktig vindustest) */ /* Frigi allokerte kjeder */ LC_POL_FrigiPolygon(&Polygon); /* Les inn traseen igjen */ LC_RxGr(&BgrTrase,LES_OPTIMALT,&ngi,&nko,&info); return (1); } } /* Frigi allokerte kjeder */ LC_POL_FrigiPolygon(&Polygon); /* Les inn traseen igjen */ LC_RxGr(&BgrTrase,LES_OPTIMALT,&ngi,&nko,&info); /* Andre gruppenavn */ } else { /* Sjekk første koordinat */ if (GM_wtst(*pdAust,*pdNord,*pdAust,*pdNord,nva,nvn,oha,ohn)) { return(1); } /* Sjekk resten av gruppen */ ++pdAust; ++pdNord; for (pt=1; ptnko; ++pt,++pdAust,++pdNord) { if (GM_wtst(*(pdAust-1),*(pdNord-1),*pdAust,*pdNord, nva,nvn,oha,ohn)) { return(1); } } } } } return (0); } /* AR-890824 CH LC_PTst Polygontest CD ========================================================================== CD Formål: CD Sjekker om gitt punkt ligger innenfor polygon angitt av aktuell gruppe. CD Forutsetter at tabellen danner et lukket polygon CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD double a i Punkt som skal sjekkes CD double n i CD short ist r status: 0 = punktet er utenfor flaten CD 1 = punktet ligger inne på flaten CD CD Bruk: CD . CD LC_SBFlate(&GeoStat,a-d,n-d,a+d,n+d); CD if (LC_FFFlate(&GeoStat,&Bgr)) { CD do{ CD LC_RxGr(&Bgr,LES_OPTIMALT,&ngi,&nko,&info); CD if (LC_PTst(a,n)){ (Nøyaktig polygontest) CD . Behandle funnet gruppe CD . CD } CD } while (LC_FNFlate(&GeoStat,&Bgr)); CD } CD LC_AvsluttSok(&GeoStat); CD . ========================================================================== */ SK_EntPnt_FYBA short LC_PTst(double a,double n) { LC_POLYGON Polygon; short inni = 0; /* Returverdi: 1 = inne på flaten, 0 = utenfor */ // Sjekk om gruppen er flate if (Sys.pGrInfo->gnavn == L_FLATE) { // Initier flatehandtering, og les flatebeskrivelsen LC_POL_InitPolygon(&Polygon); LC_POL_GetRef(&Polygon); // Utfør selve polygontesten inni = LC_POL_PTst(&Polygon,a,n); // Frigi allokerte kjeder LC_POL_FrigiPolygon(&Polygon); } return inni; } /* AR-911002 CH LC_PTstOmkrets Sjekk om punkt ligger inni polygon CD ========================================================================== CD Formål: CD Sjekker om gitt punkt ligger innenfor yttergrensen for polygon angitt CD av aktuell gruppe. CD Forutsetter at tabellen danner et lukket polygon CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD double a i Punkt som skal sjekkes CD double n i CD short ist r status: 0 = punktet er utenfor flaten CD 1 = punktet ligger inne på flaten CD CD Bruk: CD ist = LC_PTstOmkrets(a,n); ========================================================================== */ SK_EntPnt_FYBA short LC_PTstOmkrets(double a,double n) { long ref_arr[MAX_REF]; unsigned char ref_status[MAX_REF]; long ant_ref; short ngi,s; long nko; unsigned short info; LC_GRF_STATUS GrfStat; LC_BGR Bgr; short sAntSkjaer = 0; LC_BGR Flate = Sys.GrId; /* Husk gruppenummer for flaten */ Bgr.pFil = Flate.pFil; double dEnhet = Sys.pGrInfo->dEnhet; // Pluss på et lite tillegg for å unngå treff på node a += dEnhet / 1000.0; n += dEnhet / 1000.0; /* Sjekk om gruppen er flate */ if (LC_GetGrPara(&ngi,&nko,&info) == L_FLATE){ LC_InitGetRefFlate(&GrfStat); /* Behandle ytre avgrensing */ ant_ref = LC_GetRefFlate(&GrfStat,GRF_YTRE,ref_arr,ref_status,MAX_REF); do { for (s=0; s 0); } /* Sjekk om punktet er innenfor */ return ((sAntSkjaer % 2) == 1)? 1 : 0; } /* AR-921028 CH LR_PTstGruppe Sjekk om punkt ligger inni polygon CD ========================================================================== CD Formål: CD Sjekker antall skjæringer mellom gitt gruppe og linje fra gitt punkt CD til "uendelig" øst. CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_BGR * pBgr i Peker til datagruppe CD double a i Punkt som skal sjekkes CD double n i CD short sAntSkjaer r Antall skjæringer CD CD Bruk: CD ist = LR_PTstOmkrets(&Bgr,a,n); ========================================================================== */ short LR_PTstGruppe(LC_BGR * pBgr,double a,double n) { double maxa = 99999999999.0; /* "Uendelig" øst */ short ngi,gruppenavn,sfeil; long pt,nko; unsigned short info; #define ARR_LEN 50 long punkt, antall; double a1,n1,a2,n2,radius,as,ns,fi,dfi; double n_arr[ARR_LEN],a_arr[ARR_LEN]; LC_POLYGON Polygon; LC_POL_ELEMENT * pPE; LC_BGR BgrTrase; short sAntSkjaer = 0; /* Sjekk gruppen */ gruppenavn = LC_RxGr(pBgr,LES_OPTIMALT,&ngi,&nko,&info); if (nko > 0) { /* .TRASE */ if (gruppenavn == L_TRASE) { BgrTrase = Sys.GrId; /* Husk gruppenummer for traseen */ /* Initier referansehandtering, og les beskrivelsen */ LC_POL_InitPolygon(&Polygon); LC_POL_GetRef(&Polygon); /* Behandle referansene */ for (pPE = Polygon.HovedPO.pForstePE; pPE != NULL; pPE = pPE->pNestePE) { sAntSkjaer += LR_PTstGruppe(&pPE->Bgr,a,n); } /* Frigi allokerte kjeder, og les inn traseen igjen */ LC_POL_FrigiPolygon(&Polygon); LC_RxGr(&BgrTrase,LES_OPTIMALT,&ngi,&nko,&info); /* "bue" */ } else if (gruppenavn == L_BUE || gruppenavn == L_BUEP || gruppenavn == L_SIRKEL || gruppenavn == L_SIRKELP) { if (LC_GetBuePar(HENT_FORRFRA,&as,&ns,&radius,&fi,&dfi,&sfeil)) { sAntSkjaer += GM_sLinBue(as,ns,radius,fi,dfi, a,n,maxa,n,&a1,&n1,&a2,&n2); } /* Annen gruppe */ } else { punkt = 1; do { /* Finn skjæringspunkter */ LC_GetArrayTK(HENT_FORRFRA,ARR_LEN,punkt,a_arr,n_arr,&antall);/* Henter */ if (antall > 0) { for (pt=1; ptpGeoRN,&pNyRN); /* Hvis rot-noden er splittet må det lages ny rot-node */ if (pNyRN != NULL) { if (pFil->pGeoRN != NULL) { /* Lag ny rot-node */ pRotRN = LR_R_CreateRNode(NULL,LC_NODE); pRotRN->Son.pNode[0] = pFil->pGeoRN; pRotRN->Son.pNode[1] = pNyRN; pRotRN->sSonAnt = 2; /* Oppdater boks */ pRotRN->Boks = pFil->pGeoRN->Boks; LR_R_BoksSum(&(pRotRN->Boks),&(pNyRN->Boks)); /* Oppdater far i sønnene */ pFil->pGeoRN->pFar = pRotRN; pNyRN->pFar = pRotRN; pFil->pGeoRN = pRotRN; } else { pFil->pGeoRN = pNyRN; } } return pRL; } /* AR-980108 CH LR_R_Insert Insert i R-tre CD ======================================================================= CD Bruk: CD CD Parametere: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------- CD long lGrNr i Gruppenummer i filen CD LC_BOKS *pB i Boks som skal legges inn i treet CD LC_R_NODE *pFar i Peker til far i quad-treet CD LC_R_NODE *pRN i Peker til node i R-treet CD LC_R_NODE **ppNyRN u Peker til peker til nyopprettet node i R-treet CD LC_R_LEAF *pRL r Peker til forekomst i R-treet CD CD Formål: CD Leger inn et rektangl i R-treet med rot i node pRN. CD Hvis pRN == NULL (Tomt tre) settes *ppNyRN til å peke til et nyt tre. CD ======================================================================= */ static LC_R_LEAF * LR_R_Insert(long lGrNr,LC_BOKS *pB,LC_R_NODE *pFar,LC_R_NODE *pRN,LC_R_NODE **ppNyRN) { LC_R_NODE *pNyRN,*pKandidatRN[LC_R_MAX_SON+1]; LC_R_LEAF *pRL,*pKandidatRL[LC_R_MAX_SON+1]; int i,iIdxMin=0,iIdxMax=0; double dDeltaAreal,dMinDeltaAreal; double dMinAust,dMaxAust; // Test //static int iNivo; //iNivo++; //UT_FPRINTF(stderr,"LR_R_Insert nivå :%d\n",iNivo); *ppNyRN = NULL; /* Treet er tomt, må allokere ny node */ if (pRN == NULL) { *ppNyRN = pRN = LR_R_CreateRNode(NULL,LC_LEAF); } /* Har kommet til ytterste nivå */ if (pRN->sSonType == LC_LEAF) { pRL = LR_R_CreateRLeaf(lGrNr,pB,pRN); /* Hvis ledig plass */ if (pRN->sSonAnt < LC_R_MAX_SON) { /* Legg inn rektanglet */ pRN->Son.pLeaf[pRN->sSonAnt] = pRL; (pRN->sSonAnt)++; /* Oppdaterer omskrevet boks */ LR_R_BoksSum(&(pRN->Boks),pB); /* Fullt, må opprett ny node */ } else { *ppNyRN = pNyRN = LR_R_CreateRNode(pRN->pFar,LC_LEAF); /* Fordel boksene på de to nodene etter lineær kost algoritmen */ /* Beregn "ekstrem-bokser" */ dMinAust = LONG_MAX; dMaxAust = LONG_MIN; iIdxMax = 0; for (i=0; isSonAnt; i++) { pKandidatRL[i] = pRN->Son.pLeaf[i]; if (pKandidatRL[i]->Boks.dMinAust > dMaxAust) { dMaxAust = pKandidatRL[i]->Boks.dMinAust; iIdxMax = i; } } pKandidatRL[LC_R_MAX_SON] = pRL; if (pB->dMinAust > dMaxAust) { dMaxAust = pB->dMinAust; iIdxMax = LC_R_MAX_SON; } for (i=0; isSonAnt; i++) { if (iIdxMax != i) { if (pKandidatRL[i]->Boks.dMaxAust < dMinAust) { dMinAust = pKandidatRL[i]->Boks.dMaxAust; iIdxMin = i; } } } if (iIdxMax != LC_R_MAX_SON && pB->dMaxAust < dMinAust) { dMinAust = pB->dMaxAust; iIdxMin = LC_R_MAX_SON; } /* Plasser ut ekstremboksene */ pRN->Son.pLeaf[0] = pKandidatRL[iIdxMax]; pRN->sSonAnt = 1; pRN->Boks = pKandidatRL[iIdxMax]->Boks; pKandidatRL[iIdxMax]->pFar = pRN; pKandidatRL[iIdxMax] = NULL; pNyRN->Son.pLeaf[0] = pKandidatRL[iIdxMin]; pNyRN->sSonAnt = 1; pNyRN->Boks = pKandidatRL[iIdxMin]->Boks; pKandidatRL[iIdxMin]->pFar = pNyRN; pKandidatRL[iIdxMin] = NULL; /* Resten av boksene plasseres der de fører til minst utvielse av boksen */ for (i=0; i<=LC_R_MAX_SON; i++) { if (pKandidatRL[i] != NULL) { if (LR_BoksDeltaArealSum(&(pRN->Boks),&(pKandidatRL[i]->Boks)) < LR_BoksDeltaArealSum(&(pNyRN->Boks),&(pKandidatRL[i]->Boks)) ) { pRN->Son.pLeaf[pRN->sSonAnt] = pKandidatRL[i]; pRN->sSonAnt++; LR_R_BoksSum(&(pRN->Boks),&(pKandidatRL[i]->Boks)); pKandidatRL[i]->pFar = pRN; } else { pNyRN->Son.pLeaf[pNyRN->sSonAnt] = pKandidatRL[i]; pNyRN->sSonAnt++; LR_R_BoksSum(&(pNyRN->Boks),&(pKandidatRL[i]->Boks)); pKandidatRL[i]->pFar = pNyRN; } } } } /* Node */ } else { /* velg den noden som utvides minst ved tillegg av den nye boksen */ dMinDeltaAreal = LONG_MAX; iIdxMin = 0; for (i=0; isSonAnt; i++) { /* Beregn hvor mye boksen ville ha blitt utvidet hvis denne ble valget */ dDeltaAreal = LR_BoksDeltaArealSum(&(pRN->Son.pNode[i]->Boks),pB); if (dDeltaAreal < dMinDeltaAreal) { dMinDeltaAreal = dDeltaAreal; iIdxMin = i; } } /* Legger inn rektanglet i den noden med minst utvdelse */ pRL = LR_R_Insert(lGrNr,pB,pRN,pRN->Son.pNode[iIdxMin],ppNyRN); /* Denne noden har blitt splittet, dette må tas vare på her */ if (*ppNyRN != NULL) { /* Hvis ledig plass */ if (pRN->sSonAnt < LC_R_MAX_SON) { /* Legg inn rektanglet */ pRN->Son.pNode[pRN->sSonAnt] = *ppNyRN; (pRN->sSonAnt)++; /* Oppdaterer omskrevet boks */ LR_R_BoksSum(&(pRN->Boks),pB); /* Ingen splitting på nivået over */ *ppNyRN = NULL; /* Fullt, må opprett ny node */ } else { pNyRN = LR_R_CreateRNode(pFar,LC_NODE); /* Fordel boksene på de to nodene etter lineær kost algoritmen */ /* Beregn "ekstrem-bokser" */ dMinAust = LONG_MAX; dMaxAust = LONG_MIN; for (i=0; isSonAnt; i++) { pKandidatRN[i] = pRN->Son.pNode[i]; if (pKandidatRN[i]->Boks.dMinAust > dMaxAust) { dMaxAust = pKandidatRN[i]->Boks.dMinAust; iIdxMax = i; } } pKandidatRN[LC_R_MAX_SON] = *ppNyRN; if (pKandidatRN[i]->Boks.dMinAust > dMaxAust) { dMaxAust = pKandidatRN[i]->Boks.dMinAust; iIdxMax = LC_R_MAX_SON; } for (i=0; isSonAnt; i++) { if (iIdxMax != i) { if (pKandidatRN[i]->Boks.dMaxAust < dMinAust) { dMinAust = pKandidatRN[i]->Boks.dMaxAust; iIdxMin = i; } } } /* Plasser ut ekstremboksene */ pRN->Son.pNode[0] = pKandidatRN[iIdxMax]; pRN->sSonAnt = 1; pRN->Boks = pKandidatRN[iIdxMax]->Boks; pKandidatRN[iIdxMax]->pFar = pRN; pKandidatRN[iIdxMax] = NULL; pNyRN->Son.pNode[0] = pKandidatRN[iIdxMin]; pNyRN->sSonAnt = 1; pNyRN->Boks = pKandidatRN[iIdxMin]->Boks; pKandidatRN[iIdxMin]->pFar = pNyRN; pKandidatRN[iIdxMin] = NULL; /* Resten av boksene plasseres der de fører til minst utvielse av boksen */ for (i=0; i<=LC_R_MAX_SON; i++) { if (pKandidatRN[i] != NULL) { if (LR_BoksDeltaArealSum(&(pRN->Boks),&(pKandidatRN[i]->Boks)) < LR_BoksDeltaArealSum(&(pNyRN->Boks),&(pKandidatRN[i]->Boks)) ) { pRN->Son.pNode[pRN->sSonAnt] = pKandidatRN[i]; pRN->sSonAnt++; LR_R_BoksSum(&(pRN->Boks),&(pKandidatRN[i]->Boks)); pKandidatRN[i]->pFar = pRN; } else { pNyRN->Son.pNode[pNyRN->sSonAnt] = pKandidatRN[i]; pNyRN->sSonAnt++; LR_R_BoksSum(&(pNyRN->Boks),&(pKandidatRN[i]->Boks)); pKandidatRN[i]->pFar = pNyRN; } } } /* Husk den nye noden til nivået over */ *ppNyRN = pNyRN; } } else { /* Oppdater omskrevet boks for noden */ LR_R_BoksSum(&(pRN->Boks),pB); } } // Test //iNivo--; return pRL; } /* AR-980108 CH LR_R_BoksSum Summerer to bokser CD ======================================================================= CD Formål: CD Summerer to bokser ved at boks1 blir utvidet slik at den også dekker CD boks2. CD CD Parametere: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------- CD LC_BOKS * pB1 iu Boks1 som skal utvides CD LC_BOKS * pB2 i Boks2 som skal legges til boks1 CD ======================================================================= */ static void LR_R_BoksSum(LC_BOKS * pB1,LC_BOKS * pB2) { pB1->dMinAust = fymin(pB1->dMinAust,pB2->dMinAust); pB1->dMinNord = fymin(pB1->dMinNord,pB2->dMinNord); pB1->dMaxAust = fymax(pB1->dMaxAust,pB2->dMaxAust); pB1->dMaxNord = fymax(pB1->dMaxNord,pB2->dMaxNord); } /* AR-980108 CH LR_BoksDeltaArealSum Bereg arealendring ved sumering CD ======================================================================= CD Formål: CD Beregner hvor mye arealet av boks1 blir utvidet hvis den blir CD summert med boks2. CD CD Parametere: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------- CD LC_BOKS * pB1 i Boks1 CD LC_BOKS * pB2 i Boks2 CD double dDeltaAreal r Arealendring CD ======================================================================= */ static double LR_BoksDeltaArealSum(LC_BOKS * pB1,LC_BOKS * pB2) { //long lNy, lGml; //lGml = (pB1->dMaxAust - pB1->dMinAust) * (pB1->dMaxNord - pB1->dMinNord); //return (lNy - lGml); double dDeltaAreal = (fymax(pB1->dMaxAust,pB2->dMaxAust) - fymin(pB1->dMinAust,pB2->dMinAust)) * (fymax(pB1->dMaxNord,pB2->dMaxNord) - fymin(pB1->dMinNord,pB2->dMinNord)); return dDeltaAreal; } /* AR-980108 CH LR_R_Delete Fjern fra "søketreet" CD ======================================================================= CD Bruk: CD CD Parametere: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------- CD LC_R_LEAF * pRL i Peker til forekomst i R-treet CD CD Formål: CD Fjern et gitt element fra R-treet for geografisk søk. CD ======================================================================= */ void LR_R_Delete(LC_R_LEAF * pRL) { LC_R_NODE *pFar,*pRN,*pSonRN; int i,iFunnet,iIdx=0,iFerdig; if (pRL != NULL) { // Husk "far" pFar = pRL->pFar; /* Fjerner pekeren fra gruppetabellen */ Sys.pGrInfo->pRL = NULL; /* Fjern pekeren til løvet */ pRN = pFar; iFunnet = UT_FALSE; for (i=0; isSonAnt; i++) { /* Sjekk om dette er den rette pekeren */ if (iFunnet == UT_FALSE) { if (pRN->Son.pLeaf[i] == pRL) { iFunnet = UT_TRUE; iIdx = i; } /* Pakk de andre pekerne i denne noden */ } else { pRN->Son.pLeaf[iIdx] = pRN->Son.pLeaf[i]; } } if (iFunnet == UT_TRUE) { (pRN->sSonAnt)--; } // Frigir det aktuelle "løvet" UT_FREE((char *)pRL); /* Sjekk om det er mere som skal fjernes oppover i treet */ iFerdig = UT_FALSE; while ( iFerdig == UT_FALSE) { /* Antall sønner er 0, denne noden skal fjernes på nivået over */ if (pRN->sSonAnt == 0) { // Er ikke på øverste nivå if (pRN->pFar != NULL) { /* Husk noden */ pSonRN = pRN; /* Fjern pekeren til noden */ pRN = pSonRN->pFar; iFunnet = UT_FALSE; for (i=0; isSonAnt; i++) { /* Sjekk om dette er den rette pekeren */ if (iFunnet == UT_FALSE) { if (pRN->Son.pNode[i] == pSonRN) { iFunnet = UT_TRUE; iIdx = i; } /* Pakk de andre pekerne i denne noden */ } else { pRN->Son.pNode[iIdx] = pRN->Son.pNode[i]; } } if (iFunnet == UT_TRUE) { (pRN->sSonAnt)--; } /* Frigir noden */ UT_FREE((char *)pSonRN); /* Har kommet til toppen */ } else { iFerdig = UT_TRUE; /* Treet er tomt initierer verdier på nytt */ pRN->sSonType = LC_LEAF; /* Omskrevet boks initieres til stor invers verdi */ pRN->Boks.dMinAust = pRN->Boks.dMinNord = LONG_MAX; pRN->Boks.dMaxAust = pRN->Boks.dMaxNord = LONG_MIN; } /* Har flere sønner, må beregne omskrevet boks på nytt */ } else { pRN->Boks.dMinAust = pRN->Boks.dMinNord = LONG_MAX; pRN->Boks.dMaxAust = pRN->Boks.dMaxNord = LONG_MIN; if (pRN->sSonType == LC_LEAF) { for (i=0; isSonAnt; i++) { LR_R_BoksSum(&(pRN->Boks),&(pRN->Son.pLeaf[i]->Boks)); } } else { for (i=0; isSonAnt; i++) { LR_R_BoksSum(&(pRN->Boks),&(pRN->Son.pNode[i]->Boks)); } } iFerdig = UT_TRUE; } } } } /* AR-980204 CH LR_R_CreateRNode Alloker og initier R-tre-node CD ======================================================================= CD Bruk: CD CD Parametere: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------- CD LC_R_NODE * pFar i Peker til far i R-treet CD short sSonType i Hvilken type sønner har denne noden LC_NODE / LC_LEAF CD LC_R_NODE * pRN r Peker til ny node i R-tre CD CD Formål: CD Alloker og initier node i R-tre. CD ======================================================================= */ static LC_R_NODE * LR_R_CreateRNode( LC_R_NODE * pFar,short sSonType) { LC_R_NODE * pRN; pRN = (LC_R_NODE *)UT_MALLOC(sizeof(LC_R_NODE)); pRN->pFar = pFar; pRN->sSonType = sSonType; pRN->sSonAnt = 0; //for (i=0; i>LC_R_MAX_SON; i++) { // if (sSonType == LC_NODE) { // pRN->Son.pNode[i] = NULL; // } else { // pRN->Son.pLeaf[i] = NULL; // } //} /* Omskrevet boks initieres til stor invers boks */ pRN->Boks.dMinAust = pRN->Boks.dMinNord = LONG_MAX; pRN->Boks.dMaxAust = pRN->Boks.dMaxNord = LONG_MIN; return pRN; } /* AR-980204 CH LR_R_CreateRLeaf Alloker og initier R-tre-løv CD ======================================================================= CD Bruk: CD CD Parametere: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------- CD long lGrNr i Gruppenummer i filen CD LC_BOKS * pB i Boks som skal legges inn i treet CD LC_R_NODE * pFar i Peker til far i R-treet CD LC_R_LEAF * pCL r Peker til ny forekomst CD CD Formål: CD Alloker og initier løv R-tre. CD ======================================================================= */ static LC_R_LEAF * LR_R_CreateRLeaf(long lGrNr, LC_BOKS * pB,LC_R_NODE * pFar) { LC_R_LEAF * pCL = (LC_R_LEAF *)UT_MALLOC(sizeof(LC_R_LEAF)); pCL->pFar = pFar; pCL->Boks = *pB; pCL->lNr = lGrNr; return pCL; } /* AR-980113 CH LR_LeggTilKB Legg til Bgr i søkeresultat-kjede CD ======================================================================= CD Bruk: CD CD parametere: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat i Peker til struktur for søkestatus CD LC_FILADM * pFil i Filpeker CD long lNr i Gruppenummer i filen CD CD Formål: CD Legg til Bgr i kjede med søkeresultat. CD ======================================================================= */ static void LR_LeggTilKB(LC_GEO_STATUS * pGeoStat,LC_FILADM *pFil,long lNr) { LC_KJEDE_BGR * pKB; pKB = (LC_KJEDE_BGR *) UT_MALLOC(sizeof(LC_KJEDE_BGR)); /* Sosi-gruppe */ pKB->Bgr.pFil = pFil; pKB->Bgr.lNr = lNr; /* Oppdater pekerne i kjeden */ pKB->pNesteKB = NULL; if (pGeoStat->pForsteKB == NULL) { pGeoStat->pForsteKB = pKB; } else { pGeoStat->pSisteKB->pNesteKB = pKB; } pGeoStat->pSisteKB = pKB; } /* AR-980113 CH LC_AvsluttSok Avslutter geografisk søk CD ======================================================================= CD Bruk: CD CD parametere: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat i Peker til struktur for søkestatus CD CD Formål: CD Avslutter geografisk søk, og frigir kjede med søkeresultat. CD ======================================================================= */ SK_EntPnt_FYBA void LC_AvsluttSok(LC_GEO_STATUS * pGeoStat) { LC_KJEDE_BGR *pKB, *pNesteKB; pNesteKB = pGeoStat->pForsteKB; while (pNesteKB != NULL) { pKB = pNesteKB; pNesteKB = pKB->pNesteKB; UT_FREE(pKB); } pGeoStat->pForsteKB = NULL; pGeoStat->pSisteKB = NULL; pGeoStat->pAktuellKB = NULL; } /* AR-980209 CH LR_VelgMetode Velg søkemetode for geografisk søk CD ========================================================================== CD Formål: CD Velg søkemetode for geografisk søk. Bruker R-tre hvis utstrekningen av CD søkeområdet er mindre enn 10% av baseområdet i nord eller øst retning. CD CD Parametre: CD Type Navn I/U Forklaring CD -------------------------------------------------------------------------- CD LC_GEO_STATUS * pGeoStat iu Peker til struktur for søkestatus CD ========================================================================== */ static void LR_VelgMetode(LC_GEO_STATUS * pGeoStat) { LC_BOKS * pB = &Sys.pAktBase->Omraade; if ( pGeoStat->oha - pGeoStat->nva < (pB->dMaxAust - pB->dMinAust) / 10 || pGeoStat->ohn - pGeoStat->nvn < (pB->dMaxNord - pB->dMinNord) / 10 ) { pGeoStat->usMetode = LC_GEO_RTRE; } else { pGeoStat->usMetode = LC_GEO_SEKV; } } /* AR-980108 CH LR_R_FrigiGren Frigir en gren fra "søketreet" CD ======================================================================= CD Bruk: CD CD Parametere: CD Type Navn I/U Forklaring CD ----------------------------------------------------------------------- CD LC_R_NODE * pRN i Peker til node i R-treet CD CD Formål: CD Frigir en gren fra R-treet for geografisk søk. CD ======================================================================= */ void LR_R_FrigiGren(LC_R_NODE * pRN) { int i; /* Har kommet til ytterste nivå */ if (pRN->sSonType == LC_LEAF) { /* Sjekk løvene som er lagret under denne noden */ for (i=0; isSonAnt; i++) { UT_FREE((char *)pRN->Son.pLeaf[i]); } /* Node */ } else { /* Rekursiv sjekk av de underliggende nodene */ for (i=0; isSonAnt; i++) { // Vis alle underliggende nivåer LR_R_FrigiGren(pRN->Son.pNode[i]); } } UT_FREE((char *)pRN); }