* 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.
<refsection>
<title>Description</title>
<para>
- 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.
</para>
<para>
</para>
<para>Availability: 2.0.0</para>
- <para>Changed: 2.2.0 support for splitting a line by a multiline or (multi)polygon boundary was introduced.</para>
+ <para>Changed: 2.2.0 support for splitting a line by a multiline, a multipoint or (multi)polygon boundary was introduced.</para>
<note><para>To improve the robustness of ST_Split it may be convenient to <xref linkend="ST_Snap"/> 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 <ulink url="http://trac.osgeo.org/postgis/ticket/2192">#2192</ulink>).</para></note>
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);
}
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);
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; i<mp->ngeoms; ++i)
+ {
+ for (j=0; j<out->ngeoms; ++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)
{
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:
'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
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))