| | 758 | |
|---|
| | 759 | static int OGRGeometryFactoryCompareArea(const void* p1, const void* p2) |
|---|
| | 760 | { |
|---|
| | 761 | const sPolyExtended* psPoly1 = (const sPolyExtended*) p1; |
|---|
| | 762 | const sPolyExtended* psPoly2 = (const sPolyExtended*) p2; |
|---|
| | 763 | if (psPoly2->dfArea < psPoly1->dfArea) |
|---|
| | 764 | return -1; |
|---|
| | 765 | else if (psPoly2->dfArea > psPoly1->dfArea) |
|---|
| | 766 | return 1; |
|---|
| | 767 | else |
|---|
| | 768 | return 0; |
|---|
| | 769 | } |
|---|
| | 770 | |
|---|
| | 771 | static int OGRGeometryFactoryCompareByIndex(const void* p1, const void* p2) |
|---|
| | 772 | { |
|---|
| | 773 | const sPolyExtended* psPoly1 = (const sPolyExtended*) p1; |
|---|
| | 774 | const sPolyExtended* psPoly2 = (const sPolyExtended*) p2; |
|---|
| | 775 | if (psPoly1->nInitialIndex < psPoly2->nInitialIndex) |
|---|
| | 776 | return -1; |
|---|
| | 777 | else if (psPoly1->nInitialIndex > psPoly2->nInitialIndex) |
|---|
| | 778 | return 1; |
|---|
| | 779 | else |
|---|
| | 780 | return 0; |
|---|
| | 781 | } |
|---|
| | 782 | |
|---|
| 795 | | /* Setup per polygon relation, envelope and area information. */ |
|---|
| 796 | | /* -------------------------------------------------------------------- */ |
|---|
| 797 | | OGREnvelope* envelopes = new OGREnvelope[nPolygonCount]; |
|---|
| 798 | | int** relations = new int*[nPolygonCount]; |
|---|
| 799 | | double* areas = new double[nPolygonCount]; |
|---|
| | 827 | /* Setup per polygon envelope and area information. */ |
|---|
| | 828 | /* -------------------------------------------------------------------- */ |
|---|
| | 829 | sPolyExtended* asPolyEx = new sPolyExtended[nPolygonCount]; |
|---|
| | 830 | |
|---|
| 831 | | |
|---|
| 832 | | } |
|---|
| 833 | | |
|---|
| 834 | | /* This a several step algorithm : |
|---|
| 835 | | 1) Compute in a matrix how polygons relate to each other |
|---|
| 836 | | (this is the moment for detecting pathological intersections and exiting) |
|---|
| 837 | | 2) For each polygon, find the smallest enclosing polygon |
|---|
| 838 | | 3) For each polygon, compute its inclusion depth (0 means toplevel) |
|---|
| 839 | | 4) For each polygon of odd depth (= inner ring), add it to its outer ring |
|---|
| 840 | | |
|---|
| | 863 | } |
|---|
| | 864 | |
|---|
| | 865 | |
|---|
| | 866 | /* This a several steps algorithm : |
|---|
| | 867 | 1) Sort polygons by descending areas |
|---|
| | 868 | 2) For each polygon of rank i, find its smallest enclosing polygon |
|---|
| | 869 | among the polygons of rank [i-1 ... 0]. If there are no such polygon, |
|---|
| | 870 | this is a toplevel polygon. Otherwise, depending on if the enclosing |
|---|
| | 871 | polygon is toplevel or not, we can decide if we are toplevel or not |
|---|
| | 872 | 3) Re-sort the polygons to retrieve their inital order (nicer for some applications) |
|---|
| | 873 | 4) For each non toplevel polygon (= inner ring), add it to its outer ring |
|---|
| | 874 | 5) Add the toplevel polygons to the multipolygon |
|---|
| | 875 | |
|---|
| 863 | | for(i=0; !bMixedUpGeometries && go_on && i<nPolygonCount; i++) |
|---|
| 864 | | { |
|---|
| 865 | | for(j=i+1; go_on && j<nPolygonCount;j++) |
|---|
| 866 | | { |
|---|
| 867 | | OGRPoint pointI, pointJ; |
|---|
| 868 | | const OGRLinearRing* exteriorRingI = ((OGRPolygon *)papoPolygons[i])->getExteriorRing(); |
|---|
| 869 | | const OGRLinearRing* exteriorRingJ = ((OGRPolygon *)papoPolygons[j])->getExteriorRing(); |
|---|
| 870 | | exteriorRingI->getPoint(0, &pointI); |
|---|
| 871 | | exteriorRingJ->getPoint(0, &pointJ); |
|---|
| 872 | | |
|---|
| 873 | | if (areas[i] > areas[j] && envelopes[i].Contains(envelopes[j]) && |
|---|
| 874 | | ((bUseFastVersion && exteriorRingI->isPointInRing(&pointJ)) || |
|---|
| 875 | | (!bUseFastVersion && papoPolygons[i]->Contains(papoPolygons[j])))) |
|---|
| | 905 | |
|---|
| | 906 | /* The first (largest) polygon is necessarily top-level */ |
|---|
| | 907 | asPolyEx[0].bIsTopLevel = TRUE; |
|---|
| | 908 | asPolyEx[0].poEnclosingPolygon = NULL; |
|---|
| | 909 | |
|---|
| | 910 | int nCountTopLevel = 1; |
|---|
| | 911 | |
|---|
| | 912 | /* STEP 2 */ |
|---|
| | 913 | for(i=1; !bMixedUpGeometries && go_on && i<nPolygonCount; i++) |
|---|
| | 914 | { |
|---|
| | 915 | for(j=i-1; go_on && j>=0;j--) |
|---|
| | 916 | { |
|---|
| | 917 | if (asPolyEx[j].sEnvelope.Contains(asPolyEx[i].sEnvelope) && |
|---|
| | 918 | ((bUseFastVersion && asPolyEx[j].poExteriorRing->isPointInRing(&asPolyEx[i].poAPoint)) || |
|---|
| | 919 | (!bUseFastVersion && asPolyEx[j].poPolygon->Contains(asPolyEx[i].poPolygon)))) |
|---|
| 877 | | relations[i][j] = CONTAINS; |
|---|
| 878 | | relations[j][i] = IS_CONTAINED_BY; |
|---|
| 879 | | } |
|---|
| 880 | | else if (areas[j] > areas[i] && envelopes[j].Contains(envelopes[i]) && |
|---|
| 881 | | ((bUseFastVersion && exteriorRingJ->isPointInRing(&pointI)) || |
|---|
| 882 | | (!bUseFastVersion && papoPolygons[j]->Contains(papoPolygons[i])))) |
|---|
| 883 | | { |
|---|
| 884 | | relations[j][i] = CONTAINS; |
|---|
| 885 | | relations[i][j] = IS_CONTAINED_BY; |
|---|
| | 921 | if (asPolyEx[j].bIsTopLevel) |
|---|
| | 922 | { |
|---|
| | 923 | /* We are a lake */ |
|---|
| | 924 | asPolyEx[i].bIsTopLevel = FALSE; |
|---|
| | 925 | asPolyEx[i].poEnclosingPolygon = asPolyEx[j].poPolygon; |
|---|
| | 926 | } |
|---|
| | 927 | else |
|---|
| | 928 | { |
|---|
| | 929 | /* We are included in a something not toplevel (a lake), */ |
|---|
| | 930 | /* so in OGCSF we are considered as toplevel too */ |
|---|
| | 931 | nCountTopLevel ++; |
|---|
| | 932 | asPolyEx[i].bIsTopLevel = TRUE; |
|---|
| | 933 | asPolyEx[i].poEnclosingPolygon = NULL; |
|---|
| | 934 | } |
|---|
| | 935 | break; |
|---|
| 966 | | directContainerIndex[i] = jSmallestContainer; |
|---|
| 967 | | } |
|---|
| 968 | | |
|---|
| 969 | | /* Compute the inclusion depth of each polygon */ |
|---|
| 970 | | int* containedDepth = new int [nPolygonCount]; |
|---|
| 971 | | for(i=0;i<nPolygonCount;i++) |
|---|
| 972 | | { |
|---|
| 973 | | int depth = 0; |
|---|
| 974 | | int j = directContainerIndex[i]; |
|---|
| 975 | | while (j >= 0) |
|---|
| 976 | | { |
|---|
| 977 | | j = directContainerIndex[j]; |
|---|
| 978 | | depth++; |
|---|
| 979 | | } |
|---|
| 980 | | containedDepth[i] = depth; |
|---|
| 981 | | // fprintf(stderr, "%d is of depth %d\n", i, depth); |
|---|
| 982 | | } |
|---|
| 983 | | |
|---|
| 984 | | int nbTopLevelPolygons = 0; |
|---|
| 985 | | OGRPolygon** tempPolygons = new OGRPolygon*[nPolygonCount]; |
|---|
| 986 | | |
|---|
| 987 | | /* Create a copy of toplevel polygons */ |
|---|
| 988 | | for(i=0;i<nPolygonCount;i++) |
|---|
| 989 | | { |
|---|
| 990 | | if ((containedDepth[i] % 2) == 0) |
|---|
| 991 | | { |
|---|
| 992 | | nbTopLevelPolygons ++; |
|---|
| 993 | | tempPolygons[i] = (OGRPolygon*)papoPolygons[i]; |
|---|
| 994 | | papoPolygons[i] = NULL; |
|---|
| 995 | | if (nbTopLevelPolygons == 1) |
|---|
| 996 | | geom = tempPolygons[i]; |
|---|
| 997 | | } |
|---|
| 998 | | } |
|---|
| 999 | | |
|---|
| 1000 | | /* Add interior rings to toplevel polygons */ |
|---|
| 1001 | | for(i=0;i<nPolygonCount;i++) |
|---|
| 1002 | | { |
|---|
| 1003 | | if ((containedDepth[i] % 2) == 1) |
|---|
| 1004 | | { |
|---|
| 1005 | | tempPolygons[directContainerIndex[i]]->addRing( |
|---|
| 1006 | | ((OGRPolygon *)papoPolygons[i])->getExteriorRing()); |
|---|
| 1007 | | delete papoPolygons[i]; |
|---|
| 1008 | | } |
|---|
| 1009 | | } |
|---|
| 1010 | | |
|---|
| 1011 | | if (nbTopLevelPolygons > 1) |
|---|
| 1012 | | { |
|---|
| 1013 | | geom = new OGRMultiPolygon(); |
|---|
| 1014 | | |
|---|
| 1015 | | /* Add toplevel polygons to the multipolygon */ |
|---|
| 1016 | | for(i=0;i<nPolygonCount;i++) |
|---|
| 1017 | | { |
|---|
| 1018 | | if ((containedDepth[i] % 2) == 0) |
|---|
| 1019 | | { |
|---|
| 1020 | | ((OGRMultiPolygon*)geom)->addGeometryDirectly( |
|---|
| 1021 | | tempPolygons[i]); |
|---|
| 1022 | | tempPolygons[i] = NULL; |
|---|
| 1023 | | } |
|---|
| 1024 | | } |
|---|
| 1025 | | } |
|---|
| 1026 | | |
|---|
| 1027 | | delete[] tempPolygons; |
|---|
| 1028 | | delete[] directContainerIndex; |
|---|
| 1029 | | delete[] containedDepth; |
|---|
| 1030 | | } |
|---|
| 1031 | | |
|---|
| 1032 | | for(i=0;i<nPolygonCount;i++) |
|---|
| 1033 | | { |
|---|
| 1034 | | delete[] relations[i]; |
|---|
| 1035 | | } |
|---|
| 1036 | | delete[] relations; |
|---|
| 1037 | | delete[] areas; |
|---|
| 1038 | | delete[] envelopes; |
|---|
| | 1039 | } |
|---|
| | 1040 | } |
|---|
| | 1041 | |
|---|
| | 1042 | delete[] asPolyEx; |
|---|