[postgis-tickets] r14604 - #3428, ST_Points

Daniel Baston dbaston at gmail.com
Sat Jan 16 07:45:37 PST 2016


Author: dbaston
Date: 2016-01-16 07:45:37 -0800 (Sat, 16 Jan 2016)
New Revision: 14604

Modified:
   trunk/NEWS
   trunk/doc/reference_accessor.xml
   trunk/liblwgeom/cunit/cu_misc.c
   trunk/liblwgeom/cunit/cu_tester.c
   trunk/liblwgeom/cunit/cu_tester.h
   trunk/liblwgeom/liblwgeom.h.in
   trunk/liblwgeom/lwmpoint.c
   trunk/postgis/lwgeom_functions_basic.c
   trunk/postgis/postgis.sql.in
   trunk/regress/regress.sql
   trunk/regress/regress_expected
Log:
#3428, ST_Points

Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2016-01-15 17:29:22 UTC (rev 14603)
+++ trunk/NEWS	2016-01-16 15:45:37 UTC (rev 14604)
@@ -11,6 +11,7 @@
   - populate_topology_layer (Sandro Santilli)
   - #2259 ST_Voronoi (Dan Baston)
   - #3339 ST_GeneratePoints (Paul Ramsey)
+  - #3428 ST_Points (Dan Baston)
 
 PostGIS 2.2.1
 2016/01/06

Modified: trunk/doc/reference_accessor.xml
===================================================================
--- trunk/doc/reference_accessor.xml	2016-01-15 17:29:22 UTC (rev 14603)
+++ trunk/doc/reference_accessor.xml	2016-01-16 15:45:37 UTC (rev 14604)
@@ -2081,6 +2081,60 @@
 	  </refsection>
 	</refentry>
 
+	<refentry id="ST_Points">
+		<refnamediv>
+			<refname>ST_Points</refname>
+			<refpurpose>Returns a MultiPoint containing all of the coordinates of a geometry.
+			</refpurpose>
+		</refnamediv>
+
+		<refsynopsisdiv>
+			<funcsynopsis>
+				<funcprototype>
+					<funcdef>geometry <function>ST_Points</function></funcdef>
+					<paramdef>
+						<type>geometry</type>
+						<parameter>geom</parameter>
+					</paramdef>
+				</funcprototype>
+			</funcsynopsis>
+		</refsynopsisdiv>
+
+		<refsection>
+			<title>Description</title>
+
+			<para>
+				Returns a MultiPoint containing all of the coordinates of a
+				geometry.  Does not remove points that are duplicated in
+				the input geometry, including start and end points of ring geometries.
+				(If this behavior is undesired, duplicates may be removed using 
+				<xref linkend="ST_RemoveRepeatedPoints" />).
+			</para>
+				
+			<para>
+				M and Z ordinates will be preserved if present.
+			</para>
+
+			<para>&curve_support;</para>
+			<para>&Z_support;</para>
+		</refsection>
+
+		<refsection>
+			<title>Examples</title>
+		
+			<programlisting>SELECT ST_AsText(ST_Points('POLYGON Z ((30 10 4,10 30 5,40 40 6, 30 10))'));
+
+--result
+MULTIPOINT Z (30 10 4,10 30 5,40 40 6, 30 10 4)
+			</programlisting>
+		</refsection>
+
+		<refsection>
+			<title>See Also</title>
+			<para><xref linkend="ST_RemoveRepeatedPoints" /></para>
+		</refsection>
+	</refentry>
+
 	<refentry id="ST_SRID">
 	  <refnamediv>
 		<refname>ST_SRID</refname>

Modified: trunk/liblwgeom/cunit/cu_misc.c
===================================================================
--- trunk/liblwgeom/cunit/cu_misc.c	2016-01-15 17:29:22 UTC (rev 14603)
+++ trunk/liblwgeom/cunit/cu_misc.c	2016-01-16 15:45:37 UTC (rev 14604)
@@ -156,6 +156,20 @@
 	lwgeom_free(geom1);
 }
 
+static void test_lwmpoint_from_lwgeom(void)
+{
+	/* This cast is so ugly, we only want to do it once.  And not even that. */
+	LWGEOM* (*to_points)(LWGEOM*) = (LWGEOM* (*)(LWGEOM*)) &lwmpoint_from_lwgeom;
+
+	do_fn_test(to_points, "MULTIPOLYGON (EMPTY)", "MULTIPOINT EMPTY");
+	do_fn_test(to_points, "POINT (30 10)", "MULTIPOINT ((30 10))");
+	do_fn_test(to_points, "LINESTRING Z (30 10 4,10 30 5,40 40 6)", "MULTIPOINT Z (30 10 4,10 30 5, 40 40 6)");
+	do_fn_test(to_points, "POLYGON((35 10,45 45,15 40,10 20,35 10),(20 30,35 35,30 20,20 30))", "MULTIPOINT(35 10,45 45,15 40,10 20,35 10,20 30,35 35,30 20,20 30)");
+	do_fn_test(to_points, "MULTIPOINT M (10 40 1,40 30 2,20 20 3,30 10 4)", "MULTIPOINT M (10 40 1,40 30 2,20 20 3,30 10 4)");
+	do_fn_test(to_points, "COMPOUNDCURVE(CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3),(4 3, 4 5, 1 4, 0 0))", "MULTIPOINT(0 0, 2 0, 2 1, 2 3, 4 3, 4 3, 4 5, 1 4, 0 0)");
+	do_fn_test(to_points, "TIN(((80 130,50 160,80 70,80 130)),((50 160,10 190,10 70,50 160)))", "MULTIPOINT (80 130, 50 160, 80 70, 80 130, 50 160, 10 190, 10 70, 50 160)");
+}
+
 /*
 ** Used by the test harness to register the tests in this file.
 */
@@ -170,4 +184,5 @@
 	PG_ADD_TEST(suite, test_misc_wkb);
 	PG_ADD_TEST(suite, test_grid);
 	PG_ADD_TEST(suite, test_clone);
+	PG_ADD_TEST(suite, test_lwmpoint_from_lwgeom);
 }

Modified: trunk/liblwgeom/cunit/cu_tester.c
===================================================================
--- trunk/liblwgeom/cunit/cu_tester.c	2016-01-15 17:29:22 UTC (rev 14603)
+++ trunk/liblwgeom/cunit/cu_tester.c	2016-01-16 15:45:37 UTC (rev 14604)
@@ -278,3 +278,25 @@
 {
 	memset(cu_error_msg, '\0', MAX_CUNIT_ERROR_LENGTH);
 }
+
+/* Utility functions for testing */
+
+/* do_transformation_test
+ * - reads input_wkt and expected_wkt
+ * - asserts output of transfn(input) = expected
+ * - cleans up
+ */
+void
+do_fn_test(LWGEOM* (*transfn)(LWGEOM*), char *input_wkt, char *expected_wkt)
+{
+	LWGEOM* input = lwgeom_from_wkt(input_wkt, LW_PARSER_CHECK_NONE);
+	LWGEOM* expected = lwgeom_from_wkt(expected_wkt, LW_PARSER_CHECK_NONE);
+	LWGEOM* observed = transfn(input);
+
+	ASSERT_LWGEOM_EQUAL(observed, expected);
+
+	lwgeom_free(input);
+	lwgeom_free(expected);
+	lwgeom_free(observed);
+}
+

Modified: trunk/liblwgeom/cunit/cu_tester.h
===================================================================
--- trunk/liblwgeom/cunit/cu_tester.h	2016-01-15 17:29:22 UTC (rev 14603)
+++ trunk/liblwgeom/cunit/cu_tester.h	2016-01-16 15:45:37 UTC (rev 14604)
@@ -10,6 +10,8 @@
  *
  **********************************************************************/
 
+#include "liblwgeom.h"
+
 #define MAX_CUNIT_ERROR_LENGTH 512
 
 #define PG_ADD_TEST(suite, testfunc) CU_add_test(suite, #testfunc, testfunc)
@@ -41,3 +43,16 @@
   CU_ASSERT_STRING_EQUAL(o,e); \
 } while (0);
 
+#define ASSERT_LWGEOM_EQUAL(o, e) do { \
+	if ( !lwgeom_same(o, e) ) { \
+		char* wkt_o = lwgeom_to_ewkt(o); \
+		char* wkt_e = lwgeom_to_ewkt(e); \
+		fprintf(stderr, "[%s:%d]\n Expected: %s\n Obtained: %s\n", __FILE__, __LINE__, (wkt_o), (wkt_e)); \
+		lwfree(wkt_o); \
+		lwfree(wkt_e); \
+	} \
+	CU_ASSERT_TRUE(lwgeom_same(o, e)); \
+} while(0);
+
+/* Utility functions */
+void do_fn_test(LWGEOM* (*transfn)(LWGEOM*), char *input_wkt, char *expected_wkt);

Modified: trunk/liblwgeom/liblwgeom.h.in
===================================================================
--- trunk/liblwgeom/liblwgeom.h.in	2016-01-15 17:29:22 UTC (rev 14603)
+++ trunk/liblwgeom/liblwgeom.h.in	2016-01-16 15:45:37 UTC (rev 14604)
@@ -1337,8 +1337,8 @@
 extern void lwline_setPoint4d(LWLINE *line, uint32_t which, POINT4D *newpoint);
 extern LWPOLY *lwpoly_from_lwlines(const LWLINE *shell, uint32_t nholes, const LWLINE **holes);
 extern LWTRIANGLE *lwtriangle_from_lwline(const LWLINE *shell);
+extern LWMPOINT *lwmpoint_from_lwgeom(const LWGEOM *g); /* Extract the coordinates of an LWGEOM into an LWMPOINT */
 
-
 /* Some point accessors */
 extern double lwpoint_get_x(const LWPOINT *point);
 extern double lwpoint_get_y(const LWPOINT *point);

Modified: trunk/liblwgeom/lwmpoint.c
===================================================================
--- trunk/liblwgeom/lwmpoint.c	2016-01-15 17:29:22 UTC (rev 14603)
+++ trunk/liblwgeom/lwmpoint.c	2016-01-16 15:45:37 UTC (rev 14604)
@@ -120,3 +120,20 @@
 
 }
 
+LWMPOINT*
+lwmpoint_from_lwgeom(const LWGEOM *g)
+{
+	LWPOINTITERATOR* it = lwpointiterator_create(g);
+	int has_z = lwgeom_has_z(g);
+	int has_m = lwgeom_has_m(g);
+	LWMPOINT* result = lwmpoint_construct_empty(g->srid, has_z, has_m);
+	POINT4D p;
+
+	while(lwpointiterator_next(it, &p)) {
+		LWPOINT* lwp = lwpoint_make(g->srid, has_z, has_m, &p);
+		lwmpoint_add_lwpoint(result, lwp);
+	}
+
+	lwpointiterator_destroy(it);
+	return result;
+}

Modified: trunk/postgis/lwgeom_functions_basic.c
===================================================================
--- trunk/postgis/lwgeom_functions_basic.c	2016-01-15 17:29:22 UTC (rev 14603)
+++ trunk/postgis/lwgeom_functions_basic.c	2016-01-16 15:45:37 UTC (rev 14604)
@@ -2806,3 +2806,26 @@
 
   PG_RETURN_POINTER(ret);
 }
+
+Datum ST_Points(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(ST_Points);
+Datum ST_Points(PG_FUNCTION_ARGS)
+{
+	if (PG_ARGISNULL(0))
+	{
+		PG_RETURN_NULL();
+	}
+	else
+	{
+		GSERIALIZED* geom = PG_GETARG_GSERIALIZED_P(0);
+		GSERIALIZED* ret;
+		LWGEOM* lwgeom = lwgeom_from_gserialized(geom);
+		LWMPOINT* result = lwmpoint_from_lwgeom(lwgeom);
+
+		lwgeom_free(lwgeom);
+
+		ret = geometry_serialize(lwmpoint_as_lwgeom(result));
+		lwmpoint_free(result);
+		PG_RETURN_POINTER(ret);
+	}
+}

Modified: trunk/postgis/postgis.sql.in
===================================================================
--- trunk/postgis/postgis.sql.in	2016-01-15 17:29:22 UTC (rev 14603)
+++ trunk/postgis/postgis.sql.in	2016-01-16 15:45:37 UTC (rev 14604)
@@ -3313,6 +3313,12 @@
 	AS 'MODULE_PATHNAME','boundary'
 	LANGUAGE 'c' IMMUTABLE STRICT;
 
+-- Availability: 2.3.0
+CREATE OR REPLACE FUNCTION ST_Points(geometry)
+	RETURNS geometry
+	AS 'MODULE_PATHNAME', 'ST_Points'
+	LANGUAGE 'c' IMMUTABLE STRICT;
+
 -- PostGIS equivalent function: symdifference(geom1 geometry, geom2 geometry)
 CREATE OR REPLACE FUNCTION ST_SymDifference(geom1 geometry, geom2 geometry)
 	RETURNS geometry

Modified: trunk/regress/regress.sql
===================================================================
--- trunk/regress/regress.sql	2016-01-15 17:29:22 UTC (rev 14603)
+++ trunk/regress/regress.sql	2016-01-16 15:45:37 UTC (rev 14604)
@@ -238,6 +238,9 @@
 select '180', ST_AsText('GEOMETRYCOLLECTION EMPTY');
 select '181', ST_AsText('GEOMETRYCOLLECTION(TRIANGLE EMPTY,TIN EMPTY)');
 
+select '190', ST_Points(NULL) IS NULL;
+select '191', ST_AsText(ST_Points('MULTICURVE EMPTY'));
+select '192', ST_AsText(ST_Points('POLYGON((35 10,45 45,15 40,10 20,35 10),(20 30,35 35,30 20,20 30))'));
 
 -- Drop test table
 DROP table test;

Modified: trunk/regress/regress_expected
===================================================================
--- trunk/regress/regress_expected	2016-01-15 17:29:22 UTC (rev 14603)
+++ trunk/regress/regress_expected	2016-01-16 15:45:37 UTC (rev 14604)
@@ -165,3 +165,6 @@
 179|MULTICURVE EMPTY
 180|GEOMETRYCOLLECTION EMPTY
 181|GEOMETRYCOLLECTION(TRIANGLE EMPTY,TIN EMPTY)
+190|t
+191|MULTIPOINT EMPTY
+192|MULTIPOINT(35 10,45 45,15 40,10 20,35 10,20 30,35 35,30 20,20 30)



More information about the postgis-tickets mailing list