[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