]> granicus.if.org Git - postgis/commitdiff
Add support for MULTI* in ST_Split
authorSandro Santilli <strk@keybit.net>
Tue, 16 Mar 2010 22:18:59 +0000 (22:18 +0000)
committerSandro Santilli <strk@keybit.net>
Tue, 16 Mar 2010 22:18:59 +0000 (22:18 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@5444 b70326c6-7e19-0410-871a-916f4a2858ee

postgis/lwgeom_geos_split.c
regress/split.sql
regress/split_expected

index 09ff158b34b39b6b557836ca755318aaeadfceca..9365585aec66773471413290c4c61279588c1e91 100644 (file)
 
 /* #define POSTGIS_DEBUG_LEVEL 4 */
 
-/* Initializes and uses GEOS internally */
 static LWGEOM* lwline_split_by_line(LWLINE* lwgeom_in, LWLINE* blade_in);
+static LWGEOM* lwline_split_by_point(LWLINE* lwgeom_in, LWPOINT* blade_in);
+static LWGEOM* lwline_split(LWLINE* lwgeom_in, LWGEOM* blade_in);
+static LWGEOM* lwpoly_split_by_line(LWPOLY* lwgeom_in, LWLINE* blade_in);
+static LWGEOM* lwcollection_split(LWCOLLECTION* lwcoll_in, LWGEOM* blade_in);
+static LWGEOM* lwpoly_split(LWPOLY* lwpoly_in, LWGEOM* blade_in);
+static LWGEOM* lwgeom_split(LWGEOM* lwgeom_in, LWGEOM* blade_in);
+
+/* Initializes and uses GEOS internally */
 static LWGEOM*
 lwline_split_by_line(LWLINE* lwline_in, LWLINE* blade_in)
 {
@@ -129,7 +136,6 @@ lwline_split_by_line(LWLINE* lwline_in, LWLINE* blade_in)
        return (LWGEOM*)out;
 }
 
-static LWGEOM* lwline_split_by_point(LWLINE* lwgeom_in, LWPOINT* blade_in);
 static LWGEOM*
 lwline_split_by_point(LWLINE* lwline_in, LWPOINT* blade_in)
 {
@@ -195,7 +201,6 @@ lwline_split_by_point(LWLINE* lwline_in, LWPOINT* blade_in)
        return (LWGEOM*)out;
 }
 
-static LWGEOM* lwline_split(LWLINE* lwgeom_in, LWGEOM* blade_in);
 static LWGEOM*
 lwline_split(LWLINE* lwline_in, LWGEOM* blade_in)
 {
@@ -216,7 +221,6 @@ lwline_split(LWLINE* lwline_in, LWGEOM* blade_in)
 }
 
 /* Initializes and uses GEOS internally */
-static LWGEOM* lwpoly_split_by_line(LWPOLY* lwgeom_in, LWLINE* blade_in);
 static LWGEOM*
 lwpoly_split_by_line(LWPOLY* lwpoly_in, LWLINE* blade_in)
 {
@@ -368,7 +372,58 @@ lwpoly_split_by_line(LWPOLY* lwpoly_in, LWLINE* blade_in)
        return (LWGEOM*)out;
 }
 
-static LWGEOM* lwpoly_split(LWPOLY* lwpoly_in, LWGEOM* blade_in);
+static LWGEOM*
+lwcollection_split(LWCOLLECTION* lwcoll_in, LWGEOM* blade_in)
+{
+       LWGEOM** split_vector=NULL;
+       LWCOLLECTION* out;
+       size_t split_vector_capacity;
+       size_t split_vector_size=0;
+       size_t i,j;
+
+       split_vector_capacity=8;
+       split_vector = lwalloc(split_vector_capacity);
+       if ( ! split_vector ) {
+               lwerror("Out of virtual memory");
+               return NULL;
+       }
+
+       for (i=0; i<lwcoll_in->ngeoms; ++i)
+       {
+               LWCOLLECTION* col;
+               LWGEOM* split = lwgeom_split(lwcoll_in->geoms[i], blade_in);
+               /* an exception should prevent this from ever returning NULL */
+               if ( ! split ) return NULL;
+
+               col = lwgeom_as_lwcollection(split);
+               /* Output, if any, will always be a collection */
+               assert(col);
+
+               /* Reallocate split_vector if needed */
+               if ( split_vector_size + col->ngeoms > split_vector_capacity )
+               {
+                       split_vector_capacity *= 2;
+                       split_vector = lwrealloc(split_vector, split_vector_capacity);
+                       if ( ! split_vector ) {
+                               lwerror("Out of virtual memory");
+                               return NULL;
+                       }
+               }
+
+               for (j=0; j<col->ngeoms; ++j)
+               {
+                       col->geoms[j]->SRID = -1; /* strip srid */
+                       split_vector[split_vector_size++] = col->geoms[j];
+               }
+       }
+
+       /* Now split_vector has split_vector_size geometries */
+       out = lwcollection_construct(COLLECTIONTYPE, lwcoll_in->SRID,
+               NULL, split_vector_size, split_vector);
+
+       return (LWGEOM*)out;
+}
+
 static LWGEOM*
 lwpoly_split(LWPOLY* lwpoly_in, LWGEOM* blade_in)
 {
@@ -384,7 +439,6 @@ lwpoly_split(LWPOLY* lwpoly_in, LWGEOM* blade_in)
        return NULL;
 }
 
-static LWGEOM* lwgeom_split(LWGEOM* lwgeom_in, LWGEOM* blade_in);
 static LWGEOM*
 lwgeom_split(LWGEOM* lwgeom_in, LWGEOM* blade_in)
 {
@@ -396,6 +450,11 @@ lwgeom_split(LWGEOM* lwgeom_in, LWGEOM* blade_in)
        case POLYGONTYPE:
                return lwpoly_split((LWPOLY*)lwgeom_in, blade_in);
 
+       case MULTIPOLYGONTYPE:
+       case MULTILINETYPE:
+       case COLLECTIONTYPE:
+               return lwcollection_split((LWCOLLECTION*)lwgeom_in, blade_in);
+
        default:
                lwerror("Splitting of %s geometries is unsupported",
                        lwtype_name(TYPE_GETTYPE(lwgeom_in->type)));
index 596fedb593e270143ceb33fcf057edbd68ae50ad..385a6c390599e40a36d4c874a6ecdc068fb7887c 100644 (file)
@@ -42,3 +42,18 @@ select '22', st_asewkt(ST_Split('SRID=12;POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(
 
 -- Split double-hole polygon by line crossing exterior and both holes
 select '23', st_asewkt(ST_Split('SRID=12;POLYGON((0 0, 10 0, 10 10, 0 10, 0 0),(2 2, 8 2, 8 4, 2 4, 2 2),(2 6,8 6,8 8,2 8,2 6))', 'SRID=12;LINESTRING(5 -5, 5 15)'));
+
+-- Split multiline by line crossing both
+select '30', st_asewkt(st_split('SRID=10;MULTILINESTRING((0 0, 10 0),(0 5, 10 5))', 'SRID=10;LINESTRING(5 -5, 5 10)'));
+
+-- Split multiline by line crossing only one of them
+select '31', st_asewkt(st_split('SRID=10;MULTILINESTRING((0 0, 10 0),(0 5, 10 5))', 'SRID=10;LINESTRING(5 -5, 5 2)'));
+
+-- Split multiline by disjoint line
+select '32', st_asewkt(st_split('SRID=10;MULTILINESTRING((0 0, 10 0),(0 5, 10 5))', 'SRID=10;LINESTRING(5 10, 5 20)'));
+
+-- Split multiline by point on one of them 
+select '40', st_asewkt(st_split('SRID=10;MULTILINESTRING((0 0, 10 0),(0 5, 10 5))', 'SRID=10;POINT(5 0)'));
+
+-- Split multipolygon by line 
+select '50', st_asewkt(ST_Split('SRID=12;MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0),(2 2, 8 2, 8 4, 2 4, 2 2),(2 6,8 6,8 8,2 8,2 6)),((20 0,20 10, 30 10, 30 0, 20 0),(25 5, 28 5, 25 8, 25 5)))', 'SRID=12;LINESTRING(5 -5, 5 15)'));
index c1d8fefadc25c405b455e4c8bd4b543a42e63115..ac30bd366c13231715ed08dd70f974783e360111 100644 (file)
@@ -14,3 +14,8 @@ ERROR:  Splitter line has linear intersection with input
 21|SRID=12;GEOMETRYCOLLECTION(POLYGON((5 0,0 0,0 10,5 10,5 8,2 8,2 2,5 2,5 0)),POLYGON((5 10,10 10,10 0,5 0,5 2,8 2,8 8,5 8,5 10)))
 22|SRID=12;GEOMETRYCOLLECTION(POLYGON((2 0,0 0,0 10,2 10,2 0)),POLYGON((2 10,10 10,10 0,2 0,2 10),(5 2,8 2,8 8,5 8,5 2)))
 23|SRID=12;GEOMETRYCOLLECTION(POLYGON((5 0,0 0,0 10,5 10,5 8,2 8,2 6,5 6,5 4,2 4,2 2,5 2,5 0)),POLYGON((5 10,10 10,10 0,5 0,5 2,8 2,8 4,5 4,5 6,8 6,8 8,5 8,5 10)))
+30|SRID=10;GEOMETRYCOLLECTION(LINESTRING(0 0,5 0),LINESTRING(5 0,10 0),LINESTRING(0 5,5 5),LINESTRING(5 5,10 5))
+31|SRID=10;GEOMETRYCOLLECTION(LINESTRING(0 0,5 0),LINESTRING(5 0,10 0),LINESTRING(0 5,10 5))
+32|SRID=10;GEOMETRYCOLLECTION(LINESTRING(0 0,10 0),LINESTRING(0 5,10 5))
+40|SRID=10;GEOMETRYCOLLECTION(LINESTRING(0 0,5 0),LINESTRING(5 0,10 0),LINESTRING(0 5,10 5))
+50|SRID=12;GEOMETRYCOLLECTION(POLYGON((5 0,0 0,0 10,5 10,5 8,2 8,2 6,5 6,5 4,2 4,2 2,5 2,5 0)),POLYGON((5 10,10 10,10 0,5 0,5 2,8 2,8 4,5 4,5 6,8 6,8 8,5 8,5 10)),POLYGON((20 0,20 10,30 10,30 0,20 0),(25 5,28 5,25 8,25 5)))