[postgis-tickets] r16949 - ST_LocateBetween[Elevations]: Support GEOMETRYCOLLECTION

Darafei komzpa at gmail.com
Wed Oct 24 02:56:42 PDT 2018


Author: komzpa
Date: 2018-10-24 14:56:42 -0700 (Wed, 24 Oct 2018)
New Revision: 16949

Modified:
   trunk/NEWS
   trunk/configure.ac
   trunk/liblwgeom/cunit/cu_algorithm.c
   trunk/liblwgeom/liblwgeom_internal.h
   trunk/liblwgeom/lwgeom.c
   trunk/liblwgeom/lwlinearreferencing.c
   trunk/postgis/geography_inout.c
   trunk/postgis/lwgeom_functions_lrs.c
   trunk/regress/core/regress_lrs.sql
   trunk/regress/core/regress_lrs_expected
Log:
ST_LocateBetween[Elevations]: Support GEOMETRYCOLLECTION

References #4155



Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2018-10-24 14:04:14 UTC (rev 16948)
+++ trunk/NEWS	2018-10-24 21:56:42 UTC (rev 16949)
@@ -27,6 +27,8 @@
     Praliaskouski)
   - #3457, Fix raster envelope shortcut in ST_Clip (Sai-bot)
   - #4215, Use floating point compare in ST_DumpAsPolygons (Darafei Praliaskouski)
+  - #4155, Support for GEOMETRYCOLLECTION in ST_LocateBetween (Darafei
+    Praliaskouski)
 
 PostGIS 2.5.0
 2018/09/23

Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac	2018-10-24 14:04:14 UTC (rev 16948)
+++ trunk/configure.ac	2018-10-24 21:56:42 UTC (rev 16949)
@@ -60,8 +60,11 @@
 
 AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-math-errno], [_cv_nomatherrno], [-fno-math-errno], [], [CFLAGS="$CFLAGS -fno-math-errno"], [])
 AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-signed-zeros], [_cv_nosignedzeros], [-fno-signed-zeros], [], [CFLAGS="$CFLAGS -fno-signed-zeros"], [])
+AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fopenmp], [_cv_openmp], [-fopenmp], [], [CFLAGS="$CFLAGS -fopenmp"], [])
+AC_LIBTOOL_LINKER_OPTION([if $compiler supports -fopenmp], [_cv_openmp], [-fopenmp], [], [LDFLAGS="-fopenmp $LDFLAGS"], [])
 AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -std=gnu99], [_cv_std], -std=gnu99, [], [CFLAGS="-std=gnu99 $CFLAGS"], [])
 
+
 dnl
 dnl For GCC enable additional warning flags -Wall and -Wmissing-prototypes (using macro included with libtool)
 dnl

Modified: trunk/liblwgeom/cunit/cu_algorithm.c
===================================================================
--- trunk/liblwgeom/cunit/cu_algorithm.c	2018-10-24 14:04:14 UTC (rev 16948)
+++ trunk/liblwgeom/cunit/cu_algorithm.c	2018-10-24 21:56:42 UTC (rev 16949)
@@ -665,7 +665,7 @@
 	mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
 
 	/* Clip in the middle, mid-range. */
-	c = lwmline_clip_to_ordinate_range(mline, 'Y', 1.5, 2.5);
+	c = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)mline, 'Y', 1.5, 2.5);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
 	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((0 1.5,0 2,0 2.5))");
@@ -680,7 +680,7 @@
 	mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 1,1 2,1 3,1 4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
 
 	/* Clip off the top. */
-	c = lwmline_clip_to_ordinate_range(mline, 'Y', 3.5, 5.5);
+	c = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)mline, 'Y', 3.5, 5.5);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
 	CU_ASSERT_STRING_EQUAL(ewkt, "MULTILINESTRING((1 3.5,1 4),(0 3.5,0 4))");
@@ -695,7 +695,7 @@
 	mline = (LWMLINE*)lwgeom_from_wkt("MULTILINESTRING((1 0,1 -1,1 -2,1 -3,1 -4), (0 0,0 1,0 2,0 3,0 4))", LW_PARSER_CHECK_NONE);
 
 	/* Clip from 0 upwards.. */
-	c = lwmline_clip_to_ordinate_range(mline, 'Y', 0.0, 2.5);
+	c = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)mline, 'Y', 0.0, 2.5);
 	ewkt = lwgeom_to_ewkt((LWGEOM*)c);
 	//printf("c = %s\n", ewkt);
 	CU_ASSERT_STRING_EQUAL(ewkt, "GEOMETRYCOLLECTION(POINT(1 0),LINESTRING(0 0,0 1,0 2,0 2.5))");

Modified: trunk/liblwgeom/liblwgeom_internal.h
===================================================================
--- trunk/liblwgeom/liblwgeom_internal.h	2018-10-24 14:04:14 UTC (rev 16948)
+++ trunk/liblwgeom/liblwgeom_internal.h	2018-10-24 21:56:42 UTC (rev 16949)
@@ -240,9 +240,9 @@
 LWCOLLECTION *lwline_clip_to_ordinate_range(const LWLINE *line, char ordinate, double from, double to);
 
 /**
-* Clip a multi-line based on the from/to range of one of its ordinates. Use for m- and z- clipping
-*/
-LWCOLLECTION *lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to);
+ * Clip collection based on the from/to range of one of its ordinates. Use for m- and z- clipping
+ */
+LWCOLLECTION *lwcollection_clip_to_ordinate_range(const LWCOLLECTION *col, char ordinate, double from, double to);
 
 /**
 * Clip a multi-point based on the from/to range of one of its ordinates. Use for m- and z- clipping

Modified: trunk/liblwgeom/lwgeom.c
===================================================================
--- trunk/liblwgeom/lwgeom.c	2018-10-24 14:04:14 UTC (rev 16948)
+++ trunk/liblwgeom/lwgeom.c	2018-10-24 21:56:42 UTC (rev 16949)
@@ -2190,15 +2190,23 @@
 
 
 /* Prototype for recursion */
-static int lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxvertices, uint32_t depth, LWCOLLECTION *col);
+static void lwgeom_subdivide_recursive(const LWGEOM *geom,
+				       uint8_t dimension,
+				       uint32_t maxvertices,
+				       uint32_t depth,
+				       LWCOLLECTION *col);
 
-static int
-lwgeom_subdivide_recursive(const LWGEOM *geom, uint8_t dimension, uint32_t maxvertices, uint32_t depth, LWCOLLECTION *col)
+static void
+lwgeom_subdivide_recursive(const LWGEOM *geom,
+			   uint8_t dimension,
+			   uint32_t maxvertices,
+			   uint32_t depth,
+			   LWCOLLECTION *col)
 {
 	const uint32_t maxdepth = 50;
 	GBOX clip, subbox1, subbox2;
 	uint32_t nvertices = 0;
-	uint32_t i, n = 0;
+	uint32_t i;
 	uint32_t split_ordinate;
 	double width;
 	double height;
@@ -2205,7 +2213,6 @@
 	double pivot = DBL_MAX;
 	double center = DBL_MAX;
 	LWPOLY *lwpoly = NULL;
-	LWGEOM *clipped;
 
 	gbox_duplicate(lwgeom_get_bbox(geom), &clip);
 	width = clip.xmax - clip.xmin;
@@ -2217,12 +2224,8 @@
 	if ( width == 0.0 && height == 0.0 )
 	{
 		if ( geom->type == POINTTYPE && dimension == 0)
-		{
 			lwcollection_add_lwgeom(col, lwgeom_clone_deep(geom));
-			return 1;
-		}
-		else
-			return 0;
+		return;
 	}
 
 	if (width == 0.0)
@@ -2242,12 +2245,11 @@
 	if ( lwgeom_is_collection(geom) && geom->type != MULTIPOINTTYPE )
 	{
 		LWCOLLECTION *incol = (LWCOLLECTION*)geom;
-		int n = 0;
 		/* Don't increment depth yet, since we aren't actually
 		 * subdividing geometries yet */
 		for ( i = 0; i < incol->ngeoms; i++ )
-			n += lwgeom_subdivide_recursive(incol->geoms[i], dimension, maxvertices, depth, col);
-		return n;
+			lwgeom_subdivide_recursive(incol->geoms[i], dimension, maxvertices, depth, col);
+		return;
 	}
 
 	if (lwgeom_dimension(geom) < dimension)
@@ -2254,7 +2256,7 @@
 	{
 		/* We've hit a lower dimension object produced by clipping at
 		 * a shallower recursion level. Ignore it. */
-		return 0;
+		return;
 	}
 
 	/* But don't go too far. 2^50 ~= 10^15, that's enough subdivision */
@@ -2262,19 +2264,20 @@
 	if ( depth > maxdepth )
 	{
 		lwcollection_add_lwgeom(col, lwgeom_clone_deep(geom));
-		return 1;
+		return;
 	}
 
 	nvertices = lwgeom_count_vertices(geom);
 
 	/* Skip empties entirely */
-	if (nvertices == 0) return 0;
+	if (nvertices == 0)
+		return;
 
 	/* If it is under the vertex tolerance, just add it, we're done */
 	if (nvertices <= maxvertices)
 	{
 		lwcollection_add_lwgeom(col, lwgeom_clone_deep(geom));
-		return 1;
+		return;
 	}
 
 	split_ordinate = (width > height) ? 0 : 1;
@@ -2339,27 +2342,43 @@
 
 	++depth;
 
-	LWGEOM* subbox = (LWGEOM*) lwpoly_construct_envelope(geom->srid, subbox1.xmin, subbox1.ymin, subbox1.xmax, subbox1.ymax);
-	clipped = lwgeom_intersection(geom, subbox);
-	lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
-	lwgeom_free(subbox);
-	if (clipped)
+	LWCOLLECTION *col1 =
+	    lwcollection_construct_empty(COLLECTIONTYPE, geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom));
+	LWCOLLECTION *col2 =
+	    lwcollection_construct_empty(COLLECTIONTYPE, geom->srid, lwgeom_has_z(geom), lwgeom_has_m(geom));
+	//#pragma omp parallel sections
 	{
-		n += lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col);
-		lwgeom_free(clipped);
+		//#pragma omp section
+		{
+			LWGEOM *subbox = (LWGEOM *)lwpoly_construct_envelope(
+			    geom->srid, subbox1.xmin, subbox1.ymin, subbox1.xmax, subbox1.ymax);
+			LWGEOM *clipped = lwgeom_intersection(geom, subbox);
+			lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
+			lwgeom_free(subbox);
+			if (clipped)
+			{
+				lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col1);
+				lwgeom_free(clipped);
+			}
+		}
+		//#pragma omp section
+		{
+			LWGEOM *subbox = (LWGEOM *)lwpoly_construct_envelope(
+			    geom->srid, subbox2.xmin, subbox2.ymin, subbox2.xmax, subbox2.ymax);
+			LWGEOM *clipped = lwgeom_intersection(geom, subbox);
+			lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
+			lwgeom_free(subbox);
+			if (clipped)
+			{
+				lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col2);
+				lwgeom_free(clipped);
+			}
+		}
 	}
-
-	subbox = (LWGEOM*) lwpoly_construct_envelope(geom->srid, subbox2.xmin, subbox2.ymin, subbox2.xmax, subbox2.ymax);
-	clipped = lwgeom_intersection(geom, subbox);
-	lwgeom_simplify_in_place(clipped, 0.0, LW_TRUE);
-	lwgeom_free(subbox);
-	if (clipped)
-	{
-		n += lwgeom_subdivide_recursive(clipped, dimension, maxvertices, depth, col);
-		lwgeom_free(clipped);
-	}
-
-	return n;
+	col = lwcollection_concat_in_place(col, col1);
+	lwcollection_release(col1);
+	col = lwcollection_concat_in_place(col, col2);
+	lwcollection_release(col2);
 }
 
 LWCOLLECTION *
@@ -2385,7 +2404,6 @@
 	return col;
 }
 
-
 int
 lwgeom_is_trajectory(const LWGEOM *geom)
 {

Modified: trunk/liblwgeom/lwlinearreferencing.c
===================================================================
--- trunk/liblwgeom/lwlinearreferencing.c	2018-10-24 14:04:14 UTC (rev 16948)
+++ trunk/liblwgeom/lwlinearreferencing.c	2018-10-24 21:56:42 UTC (rev 16949)
@@ -462,80 +462,45 @@
 }
 
 /**
-* Clip an input MULTILINESTRING between two values, on any ordinate input.
-*/
-LWCOLLECTION*
-lwmline_clip_to_ordinate_range(const LWMLINE *mline, char ordinate, double from, double to)
+ * Clip an input COLLECTION between two values, on any ordinate input.
+ */
+LWCOLLECTION *
+lwcollection_clip_to_ordinate_range(const LWCOLLECTION *icol, char ordinate, double from, double to)
 {
 	LWCOLLECTION *lwgeom_out = NULL;
 
-	if ( ! mline )
+	if (!icol)
 	{
 		lwerror("Null input geometry.");
 		return NULL;
 	}
 
-	if ( mline->ngeoms == 1)
-	{
-		lwgeom_out = lwline_clip_to_ordinate_range(mline->geoms[0], ordinate, from, to);
-	}
+	if (icol->ngeoms == 1)
+		lwgeom_out = lwgeom_clip_to_ordinate_range(icol->geoms[0], ordinate, from, to, 0);
 	else
 	{
 		LWCOLLECTION *col;
-		char hasz = lwgeom_has_z(lwmline_as_lwgeom(mline));
-		char hasm = lwgeom_has_m(lwmline_as_lwgeom(mline));
-		uint32_t i, j;
-		char homogeneous = 1;
-		size_t geoms_size = 0;
-		lwgeom_out = lwcollection_construct_empty(MULTILINETYPE, mline->srid, hasz, hasm);
+		char hasz = lwgeom_has_z(lwcollection_as_lwgeom(icol));
+		char hasm = lwgeom_has_m(lwcollection_as_lwgeom(icol));
+		uint32_t i;
+		lwgeom_out = lwcollection_construct_empty(icol->type, icol->srid, hasz, hasm);
 		FLAGS_SET_Z(lwgeom_out->flags, hasz);
 		FLAGS_SET_M(lwgeom_out->flags, hasm);
-		for ( i = 0; i < mline->ngeoms; i ++ )
+		for (i = 0; i < icol->ngeoms; i++)
 		{
-			col = lwline_clip_to_ordinate_range(mline->geoms[i], ordinate, from, to);
-			if ( col )
+			col = lwgeom_clip_to_ordinate_range(icol->geoms[i], ordinate, from, to, 0);
+			if (col)
 			{
-				/* Something was left after the clip. */
-				if ( lwgeom_out->ngeoms + col->ngeoms > geoms_size )
-				{
-					geoms_size += 16;
-					if ( lwgeom_out->geoms )
-					{
-						lwgeom_out->geoms = lwrealloc(lwgeom_out->geoms, geoms_size * sizeof(LWGEOM*));
-					}
-					else
-					{
-						lwgeom_out->geoms = lwalloc(geoms_size * sizeof(LWGEOM*));
-					}
-				}
-				for ( j = 0; j < col->ngeoms; j++ )
-				{
-					lwgeom_out->geoms[lwgeom_out->ngeoms] = col->geoms[j];
-					lwgeom_out->ngeoms++;
-				}
-				if ( col->type != mline->type )
-				{
-					homogeneous = 0;
-				}
-				/* Shallow free the struct, leaving the geoms behind. */
-				if ( col->bbox ) lwfree(col->bbox);
-				lwfree(col->geoms);
-				lwfree(col);
+				if (col->type != icol->type)
+					lwgeom_out->type = COLLECTIONTYPE;
+				lwgeom_out = lwcollection_concat_in_place(lwgeom_out, col);
+				lwcollection_release(col);
 			}
 		}
-		if ( lwgeom_out->bbox )
-		{
-			lwgeom_refresh_bbox((LWGEOM*)lwgeom_out);
-		}
-
-		if ( ! homogeneous )
-		{
-			lwgeom_out->type = COLLECTIONTYPE;
-		}
+		if (lwgeom_out->bbox)
+			lwgeom_refresh_bbox((LWGEOM *)lwgeom_out);
 	}
-
 	return lwgeom_out;
-
 }
 
 
@@ -789,9 +754,6 @@
 	case LINETYPE:
 		out_col = lwline_clip_to_ordinate_range((LWLINE*)lwin, ordinate, from, to);
 		break;
-	case MULTILINETYPE:
-		out_col = lwmline_clip_to_ordinate_range((LWMLINE*)lwin, ordinate, from, to);
-		break;
 	case MULTIPOINTTYPE:
 		out_col = lwmpoint_clip_to_ordinate_range((LWMPOINT*)lwin, ordinate, from, to);
 		break;
@@ -798,9 +760,18 @@
 	case POINTTYPE:
 		out_col = lwpoint_clip_to_ordinate_range((LWPOINT*)lwin, ordinate, from, to);
 		break;
+	// case TRIANGLETYPE:
+	// 	out_col = lwtriangle_clip_to_ordinate_range((LWTRIANGLE*)lwin, ordinate, from, to);
+	// 	break;
+	case TINTYPE:
+	case MULTILINETYPE:
+	case MULTIPOLYGONTYPE:
+	case COLLECTIONTYPE:
+		out_col = lwcollection_clip_to_ordinate_range((LWCOLLECTION *)lwin, ordinate, from, to);
+		break;
 	default:
 		lwerror("This function does not accept %s geometries.", lwtype_name(lwin->type));
-		return NULL;;
+		return NULL;
 	}
 
 	/* Stop if result is NULL */

Modified: trunk/postgis/geography_inout.c
===================================================================
--- trunk/postgis/geography_inout.c	2018-10-24 14:04:14 UTC (rev 16948)
+++ trunk/postgis/geography_inout.c	2018-10-24 21:56:42 UTC (rev 16949)
@@ -712,7 +712,7 @@
 	result = palloc(size_result + VARHDRSZ);
 	SET_VARSIZE(result, size_result + VARHDRSZ);
 	memcpy(VARDATA(result), wkb, size_result);
-	pfree(wkb);
+	lwfree(wkb);
 
 	PG_RETURN_POINTER(result);
 }

Modified: trunk/postgis/lwgeom_functions_lrs.c
===================================================================
--- trunk/postgis/lwgeom_functions_lrs.c	2018-10-24 14:04:14 UTC (rev 16948)
+++ trunk/postgis/lwgeom_functions_lrs.c	2018-10-24 21:56:42 UTC (rev 16949)
@@ -85,7 +85,7 @@
 	GSERIALIZED *gout;
 	LWGEOM *lwin = NULL, *lwout = NULL;
 	double measure = PG_GETARG_FLOAT8(1);
-	double offset = PG_GETARG_FLOAT8(2);;
+	double offset = PG_GETARG_FLOAT8(2);
 
 	lwin = lwgeom_from_gserialized(gin);
 	lwout = lwgeom_locate_along(lwin, measure, offset);
@@ -160,7 +160,7 @@
 
 	if ( ! gserialized_has_z(geom_in) )
 	{
-		elog(ERROR,"This function only accepts LINESTRING or MULTILINESTRING with Z dimensions.");
+		elog(ERROR, "This function only accepts geometries with Z dimensions.");
 		PG_RETURN_NULL();
 	}
 

Modified: trunk/regress/core/regress_lrs.sql
===================================================================
--- trunk/regress/core/regress_lrs.sql	2018-10-24 14:04:14 UTC (rev 16948)
+++ trunk/regress/core/regress_lrs.sql	2018-10-24 21:56:42 UTC (rev 16949)
@@ -29,6 +29,9 @@
 -- Multilinestrings
 -- #3119 --
 select '#3119b', ST_AsText(ST_LocateBetweenElevations('MULTILINESTRING Z((0 0 0, 10 10 10))'::geometry, 11, 11));
+select '#4155.1', ST_AsText(ST_LocateBetweenElevations('GEOMETRYCOLLECTION(LINESTRING(0 0 0, 10 10 10))', 2, 5));
+select '#4155.2', ST_AsText(ST_LocateBetweenElevations('TIN Z EMPTY', 2, 5));
+select '#4155.3', ST_AsText(ST_LocateBetweenElevations('MULTIPOLYGON Z EMPTY', 2, 5));
 
 --- line_locate_point
 

Modified: trunk/regress/core/regress_lrs_expected
===================================================================
--- trunk/regress/core/regress_lrs_expected	2018-10-24 14:04:14 UTC (rev 16948)
+++ trunk/regress/core/regress_lrs_expected	2018-10-24 21:56:42 UTC (rev 16949)
@@ -17,6 +17,9 @@
 LINEZM_6|MULTIPOINT ZM (9.5 0.5 0.5 2)
 #3119a|MULTILINESTRING Z EMPTY
 #3119b|MULTILINESTRING Z EMPTY
+#4155.1|MULTILINESTRING Z ((2 2 2,5 5 5))
+#4155.2|TIN Z EMPTY
+#4155.3|MULTIPOLYGON Z EMPTY
 line_locate_point_1|0.528602749909894
 line_locate_point_2|1
 line_locate_point_3|0



More information about the postgis-tickets mailing list