| | 795 | |
|---|
| | 796 | static int OGRGeometryFactoryCompareArea(const void* p1, const void* p2) |
|---|
| | 797 | { |
|---|
| | 798 | const sPolyExtended* psPoly1 = (const sPolyExtended*) p1; |
|---|
| | 799 | const sPolyExtended* psPoly2 = (const sPolyExtended*) p2; |
|---|
| | 800 | if (psPoly2->dfArea < psPoly1->dfArea) |
|---|
| | 801 | return -1; |
|---|
| | 802 | else if (psPoly2->dfArea > psPoly1->dfArea) |
|---|
| | 803 | return 1; |
|---|
| | 804 | else |
|---|
| | 805 | return 0; |
|---|
| | 806 | } |
|---|
| | 807 | |
|---|
| | 808 | static int OGRGeometryFactoryCompareByIndex(const void* p1, const void* p2) |
|---|
| | 809 | { |
|---|
| | 810 | const sPolyExtended* psPoly1 = (const sPolyExtended*) p1; |
|---|
| | 811 | const sPolyExtended* psPoly2 = (const sPolyExtended*) p2; |
|---|
| | 812 | if (psPoly1->nInitialIndex < psPoly2->nInitialIndex) |
|---|
| | 813 | return -1; |
|---|
| | 814 | else if (psPoly1->nInitialIndex > psPoly2->nInitialIndex) |
|---|
| | 815 | return 1; |
|---|
| | 816 | else |
|---|
| | 817 | return 0; |
|---|
| | 818 | } |
|---|
| | 819 | |
|---|
| 832 | | /* Setup per polygon relation, envelope and area information. */ |
|---|
| 833 | | /* -------------------------------------------------------------------- */ |
|---|
| 834 | | OGREnvelope* envelopes = new OGREnvelope[nPolygonCount]; |
|---|
| 835 | | int** relations = new int*[nPolygonCount]; |
|---|
| 836 | | double* areas = new double[nPolygonCount]; |
|---|
| | 864 | /* Setup per polygon envelope and area information. */ |
|---|
| | 865 | /* -------------------------------------------------------------------- */ |
|---|
| | 866 | sPolyExtended* asPolyEx = (sPolyExtended*)VSICalloc(sizeof(sPolyExtended), nPolygonCount); |
|---|
| | 867 | |
|---|
| 868 | | |
|---|
| 869 | | } |
|---|
| 870 | | |
|---|
| 871 | | /* This a several step algorithm : |
|---|
| 872 | | 1) Compute in a matrix how polygons relate to each other |
|---|
| 873 | | (this is the moment for detecting pathological intersections and exiting) |
|---|
| 874 | | 2) For each polygon, find the smallest enclosing polygon |
|---|
| 875 | | 3) For each polygon, compute its inclusion depth (0 means toplevel) |
|---|
| 876 | | 4) For each polygon of odd depth (= inner ring), add it to its outer ring |
|---|
| 877 | | |
|---|
| | 900 | } |
|---|
| | 901 | |
|---|
| | 902 | |
|---|
| | 903 | /* This a several steps algorithm : |
|---|
| | 904 | 1) Sort polygons by descending areas |
|---|
| | 905 | 2) For each polygon of rank i, find its smallest enclosing polygon |
|---|
| | 906 | among the polygons of rank [i-1 ... 0]. If there are no such polygon, |
|---|
| | 907 | this is a toplevel polygon. Otherwise, depending on if the enclosing |
|---|
| | 908 | polygon is toplevel or not, we can decide if we are toplevel or not |
|---|
| | 909 | 3) Re-sort the polygons to retrieve their inital order (nicer for some applications) |
|---|
| | 910 | 4) For each non toplevel polygon (= inner ring), add it to its outer ring |
|---|
| | 911 | 5) Add the toplevel polygons to the multipolygon |
|---|
| | 912 | |
|---|
| 900 | | for(i=0; !bMixedUpGeometries && go_on && i<nPolygonCount; i++) |
|---|
| 901 | | { |
|---|
| 902 | | for(j=i+1; go_on && j<nPolygonCount;j++) |
|---|
| 903 | | { |
|---|
| 904 | | OGRPoint pointI, pointJ; |
|---|
| 905 | | const OGRLinearRing* exteriorRingI = ((OGRPolygon *)papoPolygons[i])->getExteriorRing(); |
|---|
| 906 | | const OGRLinearRing* exteriorRingJ = ((OGRPolygon *)papoPolygons[j])->getExteriorRing(); |
|---|
| 907 | | exteriorRingI->getPoint(0, &pointI); |
|---|
| 908 | | exteriorRingJ->getPoint(0, &pointJ); |
|---|
| 909 | | |
|---|
| 910 | | if (areas[i] > areas[j] && envelopes[i].Contains(envelopes[j]) && |
|---|
| 911 | | ((bUseFastVersion && exteriorRingI->isPointInRing(&pointJ)) || |
|---|
| 912 | | (!bUseFastVersion && papoPolygons[i]->Contains(papoPolygons[j])))) |
|---|
| | 942 | |
|---|
| | 943 | /* The first (largest) polygon is necessarily top-level */ |
|---|
| | 944 | asPolyEx[0].bIsTopLevel = TRUE; |
|---|
| | 945 | asPolyEx[0].poEnclosingPolygon = NULL; |
|---|
| | 946 | |
|---|
| | 947 | int nCountTopLevel = 1; |
|---|
| | 948 | |
|---|
| | 949 | /* STEP 2 */ |
|---|
| | 950 | for(i=1; !bMixedUpGeometries && go_on && i<nPolygonCount; i++) |
|---|
| | 951 | { |
|---|
| | 952 | for(j=i-1; go_on && j>=0;j--) |
|---|
| | 953 | { |
|---|
| | 954 | if (asPolyEx[j].sEnvelope.Contains(asPolyEx[i].sEnvelope) && |
|---|
| | 955 | ((bUseFastVersion && asPolyEx[j].poExteriorRing->isPointInRing(&asPolyEx[i].poAPoint)) || |
|---|
| | 956 | (!bUseFastVersion && asPolyEx[j].poPolygon->Contains(asPolyEx[i].poPolygon)))) |
|---|
| 914 | | relations[i][j] = CONTAINS; |
|---|
| 915 | | relations[j][i] = IS_CONTAINED_BY; |
|---|
| 916 | | } |
|---|
| 917 | | else if (areas[j] > areas[i] && envelopes[j].Contains(envelopes[i]) && |
|---|
| 918 | | ((bUseFastVersion && exteriorRingJ->isPointInRing(&pointI)) || |
|---|
| 919 | | (!bUseFastVersion && papoPolygons[j]->Contains(papoPolygons[i])))) |
|---|
| 920 | | { |
|---|
| 921 | | relations[j][i] = CONTAINS; |
|---|
| 922 | | relations[i][j] = IS_CONTAINED_BY; |
|---|
| | 958 | if (asPolyEx[j].bIsTopLevel) |
|---|
| | 959 | { |
|---|
| | 960 | /* We are a lake */ |
|---|
| | 961 | asPolyEx[i].bIsTopLevel = FALSE; |
|---|
| | 962 | asPolyEx[i].poEnclosingPolygon = asPolyEx[j].poPolygon; |
|---|
| | 963 | } |
|---|
| | 964 | else |
|---|
| | 965 | { |
|---|
| | 966 | /* We are included in a something not toplevel (a lake), */ |
|---|
| | 967 | /* so in OGCSF we are considered as toplevel too */ |
|---|
| | 968 | nCountTopLevel ++; |
|---|
| | 969 | asPolyEx[i].bIsTopLevel = TRUE; |
|---|
| | 970 | asPolyEx[i].poEnclosingPolygon = NULL; |
|---|
| | 971 | } |
|---|
| | 972 | break; |
|---|
| 1003 | | directContainerIndex[i] = jSmallestContainer; |
|---|
| 1004 | | } |
|---|
| 1005 | | |
|---|
| 1006 | | /* Compute the inclusion depth of each polygon */ |
|---|
| 1007 | | int* containedDepth = new int [nPolygonCount]; |
|---|
| 1008 | | for(i=0;i<nPolygonCount;i++) |
|---|
| 1009 | | { |
|---|
| 1010 | | int depth = 0; |
|---|
| 1011 | | int j = directContainerIndex[i]; |
|---|
| 1012 | | while (j >= 0) |
|---|
| 1013 | | { |
|---|
| 1014 | | j = directContainerIndex[j]; |
|---|
| 1015 | | depth++; |
|---|
| 1016 | | } |
|---|
| 1017 | | containedDepth[i] = depth; |
|---|
| 1018 | | // fprintf(stderr, "%d is of depth %d\n", i, depth); |
|---|
| 1019 | | } |
|---|
| 1020 | | |
|---|
| 1021 | | int nbTopLevelPolygons = 0; |
|---|
| 1022 | | OGRPolygon** tempPolygons = new OGRPolygon*[nPolygonCount]; |
|---|
| 1023 | | |
|---|
| 1024 | | /* Create a copy of toplevel polygons */ |
|---|
| 1025 | | for(i=0;i<nPolygonCount;i++) |
|---|
| 1026 | | { |
|---|
| 1027 | | if ((containedDepth[i] % 2) == 0) |
|---|
| 1028 | | { |
|---|
| 1029 | | nbTopLevelPolygons ++; |
|---|
| 1030 | | tempPolygons[i] = (OGRPolygon*)papoPolygons[i]; |
|---|
| 1031 | | papoPolygons[i] = NULL; |
|---|
| 1032 | | if (nbTopLevelPolygons == 1) |
|---|
| 1033 | | geom = tempPolygons[i]; |
|---|
| 1034 | | } |
|---|
| 1035 | | } |
|---|
| 1036 | | |
|---|
| 1037 | | /* Add interior rings to toplevel polygons */ |
|---|
| 1038 | | for(i=0;i<nPolygonCount;i++) |
|---|
| 1039 | | { |
|---|
| 1040 | | if ((containedDepth[i] % 2) == 1) |
|---|
| 1041 | | { |
|---|
| 1042 | | tempPolygons[directContainerIndex[i]]->addRing( |
|---|
| 1043 | | ((OGRPolygon *)papoPolygons[i])->getExteriorRing()); |
|---|
| 1044 | | delete papoPolygons[i]; |
|---|
| 1045 | | } |
|---|
| 1046 | | } |
|---|
| 1047 | | |
|---|
| 1048 | | if (nbTopLevelPolygons > 1) |
|---|
| 1049 | | { |
|---|
| 1050 | | geom = new OGRMultiPolygon(); |
|---|
| 1051 | | |
|---|
| 1052 | | /* Add toplevel polygons to the multipolygon */ |
|---|
| 1053 | | for(i=0;i<nPolygonCount;i++) |
|---|
| 1054 | | { |
|---|
| 1055 | | if ((containedDepth[i] % 2) == 0) |
|---|
| 1056 | | { |
|---|
| 1057 | | ((OGRMultiPolygon*)geom)->addGeometryDirectly( |
|---|
| 1058 | | tempPolygons[i]); |
|---|
| 1059 | | tempPolygons[i] = NULL; |
|---|
| 1060 | | } |
|---|
| 1061 | | } |
|---|
| 1062 | | } |
|---|
| 1063 | | |
|---|
| 1064 | | delete[] tempPolygons; |
|---|
| 1065 | | delete[] directContainerIndex; |
|---|
| 1066 | | delete[] containedDepth; |
|---|
| 1067 | | } |
|---|
| 1068 | | |
|---|
| 1069 | | for(i=0;i<nPolygonCount;i++) |
|---|
| 1070 | | { |
|---|
| 1071 | | delete[] relations[i]; |
|---|
| 1072 | | } |
|---|
| 1073 | | delete[] relations; |
|---|
| 1074 | | delete[] areas; |
|---|
| 1075 | | delete[] envelopes; |
|---|
| | 1076 | } |
|---|
| | 1077 | } |
|---|
| | 1078 | |
|---|
| | 1079 | CPLFree(asPolyEx); |
|---|