/* #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)
{
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)
{
return (LWGEOM*)out;
}
-static LWGEOM* lwline_split(LWLINE* lwgeom_in, LWGEOM* blade_in);
static LWGEOM*
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)
{
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)
{
return NULL;
}
-static LWGEOM* lwgeom_split(LWGEOM* lwgeom_in, LWGEOM* blade_in);
static LWGEOM*
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)));
-- 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)'));
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)))