From: Sandro Santilli Date: Wed, 22 Apr 2015 15:25:42 +0000 (+0000) Subject: Allow splitting lines by multipoints X-Git-Tag: 2.2.0rc1~554 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ca80d60917826f3fdd66aaee970f6237a887421e;p=postgis Allow splitting lines by multipoints git-svn-id: http://svn.osgeo.org/postgis/trunk@13434 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index 920c55eed..7da25d146 100644 --- a/NEWS +++ b/NEWS @@ -63,7 +63,8 @@ PostGIS 2.2.0 * Enhancements * - - Allow splitting lines by multilines and (multi)polygon boundaries + - ST_Split: allow splitting lines by multilines, multipoints + and (multi)polygon boundaries - #3070, Simplify geometry type constraint - #2839, Implement selectivity estimator for functional indexes, speeding up spatial queries on raster tables. diff --git a/doc/reference_processing.xml b/doc/reference_processing.xml index e6e60e6ad..c1a545ee9 100644 --- a/doc/reference_processing.xml +++ b/doc/reference_processing.xml @@ -2868,7 +2868,7 @@ LINESTRING M (5 2 3.40282346638529e+38,3 8 29,6 20 1.5,7 25 49.5,10 10 3.4028234 Description - The function supports splitting a line by point, a line by (multi)line or (multi)polygon boundary, a polygon by line. The returned geometry is always a collection. + The function supports splitting a line by (multi)point, (multi)line or (multi)polygon boundary, a polygon by line. The returned geometry is always a collection. @@ -2878,7 +2878,7 @@ LINESTRING M (5 2 3.40282346638529e+38,3 8 29,6 20 1.5,7 25 49.5,10 10 3.4028234 Availability: 2.0.0 - Changed: 2.2.0 support for splitting a line by a multiline or (multi)polygon boundary was introduced. + Changed: 2.2.0 support for splitting a line by a multiline, a multipoint or (multi)polygon boundary was introduced. To improve the robustness of ST_Split it may be convenient to the input to the blade in advance using a very low tolerance. Otherwise the internally used coordinate grid may cause tolerance problems, where coordinates of input and blade do not fall onto each other and the input is not being split correctly (see #2192). diff --git a/liblwgeom/cunit/cu_split.c b/liblwgeom/cunit/cu_split.c index 2a8fcdb1a..205b9a5e4 100644 --- a/liblwgeom/cunit/cu_split.c +++ b/liblwgeom/cunit/cu_split.c @@ -231,6 +231,24 @@ static void test_lwgeom_split(void) lwgeom_free(ret); lwgeom_free(geom); lwgeom_free(blade); + + /* Split line by multipoint */ + geom = lwgeom_from_wkt("LINESTRING(0 0, 10 0)", LW_PARSER_CHECK_NONE); + CU_ASSERT_FATAL(geom != NULL); + blade = lwgeom_from_wkt("MULTIPOINT(2 0,8 0,4 0)", LW_PARSER_CHECK_NONE); + ret = lwgeom_split(geom, blade); + if ( ! ret ) printf("%s", cu_error_msg); + CU_ASSERT_FATAL(ret != NULL); + wkt = lwgeom_to_ewkt(ret); + CU_ASSERT_FATAL(wkt != NULL); + in_wkt = "GEOMETRYCOLLECTION(LINESTRING(8 0,10 0),LINESTRING(0 0,2 0),LINESTRING(4 0,8 0),LINESTRING(2 0,4 0))"; + if (strcmp(in_wkt, wkt)) + fprintf(stderr, "\nExp: %s\nObt: %s\n", in_wkt, wkt); + CU_ASSERT_STRING_EQUAL(wkt, in_wkt); + lwfree(wkt); + lwgeom_free(ret); + lwgeom_free(geom); + lwgeom_free(blade); } diff --git a/liblwgeom/lwgeom_geos_split.c b/liblwgeom/lwgeom_geos_split.c index 89d66816d..83665c698 100644 --- a/liblwgeom/lwgeom_geos_split.c +++ b/liblwgeom/lwgeom_geos_split.c @@ -43,6 +43,7 @@ static LWGEOM* lwline_split_by_line(const LWLINE* lwgeom_in, const LWGEOM* blade_in); static LWGEOM* lwline_split_by_point(const LWLINE* lwgeom_in, const LWPOINT* blade_in); +static LWGEOM* lwline_split_by_mpoint(const LWLINE* lwgeom_in, const LWMPOINT* blade_in); static LWGEOM* lwline_split(const LWLINE* lwgeom_in, const LWGEOM* blade_in); static LWGEOM* lwpoly_split_by_line(const LWPOLY* lwgeom_in, const LWLINE* blade_in); static LWGEOM* lwcollection_split(const LWCOLLECTION* lwcoll_in, const LWGEOM* blade_in); @@ -178,6 +179,43 @@ lwline_split_by_point(const LWLINE* lwline_in, const LWPOINT* blade_in) return (LWGEOM*)out; } +static LWGEOM* +lwline_split_by_mpoint(const LWLINE* lwline_in, const LWMPOINT* mp) +{ + LWMLINE* out; + int i, j; + + out = lwmline_construct_empty(lwline_in->srid, + FLAGS_GET_Z(lwline_in->flags), + FLAGS_GET_M(lwline_in->flags)); + lwmline_add_lwline(out, lwline_clone(lwline_in)); + + for (i=0; ingeoms; ++i) + { + for (j=0; jngeoms; ++j) + { + lwline_in = out->geoms[j]; + LWPOINT *blade_in = mp->geoms[i]; + int ret = lwline_split_by_point_to(lwline_in, blade_in, out); + if ( 2 == ret ) + { + /* the point splits this line, + * 2 splits were added to collection. + * We'll move the latest added into + * the slot of the current one. + */ + lwline_free(out->geoms[j]); + out->geoms[j] = out->geoms[--out->ngeoms]; + } + } + } + + /* Turn multiline into collection */ + out->type = COLLECTIONTYPE; + + return (LWGEOM*)out; +} + int lwline_split_by_point_to(const LWLINE* lwline_in, const LWPOINT* blade_in, LWMLINE* v) @@ -247,6 +285,8 @@ lwline_split(const LWLINE* lwline_in, const LWGEOM* blade_in) { case POINTTYPE: return lwline_split_by_point(lwline_in, (LWPOINT*)blade_in); + case MULTIPOINTTYPE: + return lwline_split_by_mpoint(lwline_in, (LWMPOINT*)blade_in); case LINETYPE: case MULTILINETYPE: diff --git a/regress/split.sql b/regress/split.sql index 1906fdc53..cb110e39d 100644 --- a/regress/split.sql +++ b/regress/split.sql @@ -96,4 +96,10 @@ select '85', st_asewkt(ST_Split( 'SRID=3;MULTIPOLYGON(((0 -1,0 -3,2 -3,2 -1,0 -1)),((3 0,3 2,5 2,5 0,3 0)))' )); +-- Split multiline by multipoint +select '86', st_asewkt(ST_Split( + 'SRID=3;MULTILINESTRING((0 0,10 0),(5 -5, 5 5),(0 20,10 20))', + 'SRID=3;MULTIPOINT(2 6,5 0,5 20,2 20,8 20,8 0,5 -2,0 0, 5 -5, 10 20)' +)); + -- TODO: split line by collapsed line diff --git a/regress/split_expected b/regress/split_expected index e4ebfee10..64735cf0c 100644 --- a/regress/split_expected +++ b/regress/split_expected @@ -27,3 +27,4 @@ ERROR: Splitter line has linear intersection with input 83|SRID=3;GEOMETRYCOLLECTION(LINESTRING(1 -1,1 0),LINESTRING(1 0,1 1)) 84|SRID=3;GEOMETRYCOLLECTION(LINESTRING(1 -1,1 0),LINESTRING(1 0,1 1)) 85|SRID=3;GEOMETRYCOLLECTION(LINESTRING(1 -2,1 -1),LINESTRING(1 -1,1 1,3 1),LINESTRING(3 1,4 1)) +86|SRID=3;GEOMETRYCOLLECTION(LINESTRING(8 0,10 0),LINESTRING(0 0,5 0),LINESTRING(5 0,8 0),LINESTRING(5 0,5 5),LINESTRING(5 -2,5 0),LINESTRING(5 -5,5 -2),LINESTRING(8 20,10 20),LINESTRING(2 20,5 20),LINESTRING(0 20,2 20),LINESTRING(5 20,8 20))