[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0beta1-10-ga7053ec

git at osgeo.org git at osgeo.org
Fri Dec 11 02:03:05 PST 2020


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".

The branch, master has been updated
       via  a7053ec1333935d0afcf78d7f56eb197b8ff3db5 (commit)
      from  2b8b57d1141e502a3c167337543b306adc75fb74 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit a7053ec1333935d0afcf78d7f56eb197b8ff3db5
Author: Sandro Santilli <strk at kbt.io>
Date:   Tue Dec 8 22:57:20 2020 +0100

    Have ST_MakeValid remove coordinates with NaN values
    
    Closes #4813

diff --git a/NEWS b/NEWS
index 9ca3cf3..03c674c 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,7 @@ Only tickets not included in 3.1.0beta1
            to GEOS (Sandro Santilli)
   - #4815, Fix GEOS conversion of POINT EMPTY to retain type
            (Sandro Santilli)
+  - #4813, ST_MakeValid removing NaN coordinates (Sandro Santilli)
 
 PostGIS 3.1.0beta1
 2020/12/09
@@ -31,6 +32,7 @@ Only tickets not included in 3.1.0alpha3
   - Fix axis order issue with urn:ogc:def:crs:EPSG in ST_GeomFromGML()
            (Even Roualt)
 
+
 PostGIS 3.1.0alpha3
 2020/11/19
 Only tickets not included in 3.1.0alpha2
diff --git a/doc/reference_validation.xml b/doc/reference_validation.xml
index adc0d40..56461a1 100644
--- a/doc/reference_validation.xml
+++ b/doc/reference_validation.xml
@@ -320,6 +320,7 @@ SELECT ST_IsValidReason('LINESTRING(220227 150406,2220227 150407,222020 150410)'
     <para>Availability: 2.0.0</para>
     <para>Enhanced: 2.0.1, speed improvements</para>
     <para>Enhanced: 2.1.0, added support for GEOMETRYCOLLECTION and MULTIPOINT.</para>
+    <para>Enhanced: 3.1.0, added removal of Coordinates with NaN values.</para>
 
     <para>&Z_support;</para>
 
diff --git a/liblwgeom/lwgeom_geos_clean.c b/liblwgeom/lwgeom_geos_clean.c
index 9ef3108..3714e63 100644
--- a/liblwgeom/lwgeom_geos_clean.c
+++ b/liblwgeom/lwgeom_geos_clean.c
@@ -22,6 +22,9 @@
  *
  **********************************************************************/
 
+#include "../postgis_config.h"
+/*#define POSTGIS_DEBUG_LEVEL 4*/
+
 #include "liblwgeom.h"
 #include "lwgeom_geos.h"
 #include "liblwgeom_internal.h"
@@ -31,7 +34,6 @@
 #include <stdlib.h>
 #include <assert.h>
 
-/* #define POSTGIS_DEBUG_LEVEL 4 */
 /* #define PARANOIA_LEVEL 2 */
 #undef LWGEOM_PROFILE_MAKEVALID
 
@@ -116,6 +118,36 @@ LWGEOM* lwline_make_geos_friendly(LWLINE* line);
 LWGEOM* lwpoly_make_geos_friendly(LWPOLY* poly);
 POINTARRAY* ring_make_geos_friendly(POINTARRAY* ring);
 
+static void
+ptarray_strip_nan_coords_in_place(POINTARRAY *pa)
+{
+	uint32_t i, j = 0;
+	POINT4D *p, *np;
+	int ndims = FLAGS_NDIMS(pa->flags);
+	for ( i = 0; i < pa->npoints; i++ )
+	{
+		int isnan = 0;
+		p = (POINT4D *)(getPoint_internal(pa, i));
+		if ( isnan(p->x) || isnan(p->y) ) isnan = 1;
+		else if (ndims > 2 && isnan(p->z) ) isnan = 1;
+		else if (ndims > 3 && isnan(p->m) ) isnan = 1;
+		if ( isnan ) continue;
+
+		np = (POINT4D *)(getPoint_internal(pa, j++));
+		if ( np != p ) {
+			np->x = p->x;
+			np->y = p->y;
+			if (ndims > 2)
+				np->z = p->z;
+			if (ndims > 3)
+				np->m = p->m;
+		}
+	}
+	pa->npoints = j;
+}
+
+
+
 /*
  * Ensure the geometry is "structurally" valid
  * (enough for GEOS to accept it)
@@ -129,10 +161,8 @@ lwgeom_make_geos_friendly(LWGEOM* geom)
 	switch (geom->type)
 	{
 	case POINTTYPE:
-	case MULTIPOINTTYPE:
-		/* a point is always valid */
+		ptarray_strip_nan_coords_in_place(((LWPOINT*)geom)->point);
 		return geom;
-		break;
 
 	case LINETYPE:
 		/* lines need at least 2 points */
@@ -147,6 +177,7 @@ lwgeom_make_geos_friendly(LWGEOM* geom)
 	case MULTILINETYPE:
 	case MULTIPOLYGONTYPE:
 	case COLLECTIONTYPE:
+	case MULTIPOINTTYPE:
 		return lwcollection_make_geos_friendly((LWCOLLECTION*)geom);
 		break;
 
@@ -170,8 +201,7 @@ lwgeom_make_geos_friendly(LWGEOM* geom)
  * constructed POINTARRAY.
  * TODO: move in ptarray.c
  */
-POINTARRAY* ptarray_close2d(POINTARRAY* ring);
-POINTARRAY*
+static POINTARRAY*
 ptarray_close2d(POINTARRAY* ring)
 {
 	POINTARRAY* newring;
@@ -193,6 +223,8 @@ ring_make_geos_friendly(POINTARRAY* ring)
 	POINTARRAY* closedring;
 	POINTARRAY* ring_in = ring;
 
+	ptarray_strip_nan_coords_in_place(ring_in);
+
 	/* close the ring if not already closed (2d only) */
 	closedring = ptarray_close2d(ring);
 	if (closedring != ring) ring = closedring;
@@ -259,6 +291,8 @@ lwline_make_geos_friendly(LWLINE* line)
 {
 	LWGEOM* ret;
 
+	ptarray_strip_nan_coords_in_place(line->points);
+
 	if (line->points->npoints == 1) /* 0 is fine, 2 is fine */
 	{
 #if 1
@@ -858,6 +892,8 @@ lwgeom_make_valid(LWGEOM* lwgeom_in)
 	GEOSGeometry* geosout;
 	LWGEOM* lwgeom_out;
 
+	LWDEBUG(1, "lwgeom_make_valid enter");
+
 	is3d = FLAGS_GET_Z(lwgeom_in->flags);
 
 	/*
@@ -867,7 +903,9 @@ lwgeom_make_valid(LWGEOM* lwgeom_in)
 
 	initGEOS(lwgeom_geos_error, lwgeom_geos_error);
 
-	lwgeom_out = lwgeom_in;
+	lwgeom_out = lwgeom_make_geos_friendly(lwgeom_in);
+	if (!lwgeom_out) lwerror("Could not make a geos friendly geometry out of input");
+
 	geosgeom = LWGEOM2GEOS(lwgeom_out, 1);
 	if (!geosgeom)
 	{
@@ -876,8 +914,6 @@ lwgeom_make_valid(LWGEOM* lwgeom_in)
 			 " - will try cleaning that up first",
 			 lwgeom_geos_errmsg);
 
-		lwgeom_out = lwgeom_make_geos_friendly(lwgeom_out);
-		if (!lwgeom_out) lwerror("Could not make a valid geometry out of input");
 
 		/* try again as we did cleanup now */
 		/* TODO: invoke LWGEOM2GEOS directly with autoclean ? */
diff --git a/postgis/lwgeom_geos_clean.c b/postgis/lwgeom_geos_clean.c
index 12ce779..36228e6 100644
--- a/postgis/lwgeom_geos_clean.c
+++ b/postgis/lwgeom_geos_clean.c
@@ -27,7 +27,10 @@
 #include "fmgr.h"
 #include "funcapi.h"
 
+
 #include "../postgis_config.h"
+/*#define POSTGIS_DEBUG_LEVEL 4*/
+
 #include "lwgeom_geos.h"
 #include "liblwgeom.h"
 #include "lwgeom_pg.h"
@@ -35,8 +38,6 @@
 #include <string.h>
 #include <assert.h>
 
-/* #define POSTGIS_DEBUG_LEVEL 4 */
-
 Datum ST_MakeValid(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(ST_MakeValid);
 Datum ST_MakeValid(PG_FUNCTION_ARGS)
@@ -47,6 +48,8 @@ Datum ST_MakeValid(PG_FUNCTION_ARGS)
 	in = PG_GETARG_GSERIALIZED_P(0);
 	lwgeom_in = lwgeom_from_gserialized(in);
 
+	POSTGIS_DEBUG(1, "ST_MakeValid enter");
+
 	switch ( lwgeom_in->type )
 	{
 	case POINTTYPE:
diff --git a/regress/core/clean.sql b/regress/core/clean.sql
index d641075..cc3460a 100644
--- a/regress/core/clean.sql
+++ b/regress/core/clean.sql
@@ -49,4 +49,46 @@ SELECT '#1719.1', ST_AsEWKT(ST_MakeValid('POINT(0 0)'));
 SELECT '#1719.2', ST_AsEWKT(ST_Normalize(ST_MakeValid('GEOMETRYCOLLECTION(POINT(0 0),MULTIPOINT(3 4,5 2),LINESTRING(4 4, 4 4),POLYGON((0 0,10 10,0 10,10 0,0 0)))')));
 SELECT '#1719.3', ST_AsEWKT(ST_MakeValid('MULTIPOINT(3 4,5 2)'));
 
+
+SELECT '#4813.0', ST_AsEWKT(ST_MakeValid(ST_SetSRID(ST_MakePoint('NaN', 'NaN'), 4326)));
+SELECT '#4813.1', ST_AsEWKT(ST_MakeValid(ST_SetSRID(ST_Collect(p), 4326))) FROM (
+		SELECT ST_MakePoint('NaN', 'NaN') as p UNION ALL
+		SELECT ST_MakePoint(1, 0) as p UNION ALL
+		SELECT ST_MakePoint('NaN', 'NaN') UNION ALL
+		SELECT ST_MakePoint(10, 10) UNION ALL
+		SELECT ST_MakePoint('NaN', 'NaN') UNION ALL
+		SELECT ST_MakePoint('NaN', 'NaN') UNION ALL
+		SELECT ST_MakePoint('NaN', 'NaN')
+) foo;
+SELECT '#4813.10', ST_AsEWKT(ST_MakeValid(ST_SetSRID(ST_MakeLine(p), 4326))) FROM (
+	SELECT ST_MakePoint('NaN', 'NaN') as p
+) foo;
+SELECT '#4813.11', ST_AsEWKT(ST_MakeValid(ST_SetSRID(ST_MakeLine(p), 4326))) FROM (
+	SELECT ST_MakePoint(1, 0) as p UNION ALL
+	SELECT ST_MakePoint('NaN', 'NaN')
+) foo;
+SELECT '#4813.12', ST_AsEWKT(ST_MakeValid(ST_SetSRID(ST_MakeLine(p), 4326))) FROM (
+	SELECT ST_MakePoint(1, 0) as p UNION ALL
+	SELECT ST_MakePoint('NaN', 'NaN') UNION ALL
+	SELECT ST_MakePoint(2, 0)
+) foo;
+SELECT '#4813.13', ST_AsEWKT(ST_MakeValid(ST_SetSRID(ST_MakeLine(p), 4326))) FROM (
+	SELECT ST_MakePoint(1, 0) as p UNION ALL
+	SELECT ST_MakePoint(2, 0) UNION ALL
+	SELECT ST_MakePoint('NaN', 'NaN')
+) foo;
+SELECT '#4813.20', ST_AsEWKT(ST_MakeValid(ST_SetSRID(ST_MakePolygon(r), 4326))) FROM (
+	SELECT ST_MakeLine(p) as r FROM (
+			SELECT ST_MakePoint(1, 0) as p UNION ALL
+			SELECT ST_MakePoint(10, 0) UNION ALL
+			SELECT ST_MakePoint('NaN', 'NaN') UNION ALL
+			SELECT ST_MakePoint(10, 10) UNION ALL
+			SELECT ST_MakePoint('NaN', 'NaN') UNION ALL
+			SELECT ST_MakePoint(0, 10) UNION ALL
+			SELECT ST_MakePoint('NaN', 'NaN') UNION ALL
+			SELECT ST_MakePoint('NaN', 'NaN') UNION ALL
+			SELECT ST_MakePoint(1, 0)
+	) foo
+) bar;
+
 DROP TABLE clean_cases;
diff --git a/regress/core/clean_expected b/regress/core/clean_expected
index 307d75b..396dd5d 100644
--- a/regress/core/clean_expected
+++ b/regress/core/clean_expected
@@ -29,3 +29,10 @@ RT|17.1|t|t|f
 #1719.1|POINT(0 0)
 #1719.2|GEOMETRYCOLLECTION(MULTIPOLYGON(((0 10,10 10,5 5,0 10)),((0 0,5 5,10 0,0 0))),MULTIPOINT(5 2,3 4),POINT(4 4),POINT(0 0))
 #1719.3|MULTIPOINT(3 4,5 2)
+#4813.0|SRID=4326;POINT EMPTY
+#4813.1|SRID=4326;MULTIPOINT(EMPTY,1 0,EMPTY,10 10,EMPTY,EMPTY,EMPTY)
+#4813.10|SRID=4326;LINESTRING EMPTY
+#4813.11|SRID=4326;POINT(1 0)
+#4813.12|SRID=4326;LINESTRING(1 0,2 0)
+#4813.13|SRID=4326;LINESTRING(1 0,2 0)
+#4813.20|SRID=4326;POLYGON((1 0,10 0,10 10,0 10,1 0))

-----------------------------------------------------------------------

Summary of changes:
 NEWS                          |  2 ++
 doc/reference_validation.xml  |  1 +
 liblwgeom/lwgeom_geos_clean.c | 54 +++++++++++++++++++++++++++++++++++--------
 postgis/lwgeom_geos_clean.c   |  7 ++++--
 regress/core/clean.sql        | 42 +++++++++++++++++++++++++++++++++
 regress/core/clean_expected   |  7 ++++++
 6 files changed, 102 insertions(+), 11 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list