From ad5ca36e9a5aca989caf066f31a4d1c56efa5efb Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Tue, 16 Mar 2010 22:18:59 +0000 Subject: [PATCH] Add support for MULTI* in ST_Split git-svn-id: http://svn.osgeo.org/postgis/trunk@5444 b70326c6-7e19-0410-871a-916f4a2858ee --- postgis/lwgeom_geos_split.c | 71 +++++++++++++++++++++++++++++++++---- regress/split.sql | 15 ++++++++ regress/split_expected | 5 +++ 3 files changed, 85 insertions(+), 6 deletions(-) diff --git a/postgis/lwgeom_geos_split.c b/postgis/lwgeom_geos_split.c index 09ff158b3..9365585ae 100644 --- a/postgis/lwgeom_geos_split.c +++ b/postgis/lwgeom_geos_split.c @@ -45,8 +45,15 @@ /* #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; ingeoms; ++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; jngeoms; ++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))); diff --git a/regress/split.sql b/regress/split.sql index 596fedb59..385a6c390 100644 --- a/regress/split.sql +++ b/regress/split.sql @@ -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)')); diff --git a/regress/split_expected b/regress/split_expected index c1d8fefad..ac30bd366 100644 --- a/regress/split_expected +++ b/regress/split_expected @@ -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))) -- 2.40.0