[postgis-tickets] r17651 - Handle POINT EMPTY in shape loader/dumper

Paul Ramsey pramsey at cleverelephant.ca
Wed Jul 31 02:41:58 PDT 2019


Author: pramsey
Date: 2019-07-31 14:41:58 -0700 (Wed, 31 Jul 2019)
New Revision: 17651

Modified:
   branches/2.4/NEWS
   branches/2.4/loader/pgsql2shp-core.c
   branches/2.4/loader/shp2pgsql-core.c
Log:
Handle POINT EMPTY in shape loader/dumper 
References #4437



Modified: branches/2.4/NEWS
===================================================================
--- branches/2.4/NEWS	2019-07-31 21:41:51 UTC (rev 17650)
+++ branches/2.4/NEWS	2019-07-31 21:41:58 UTC (rev 17651)
@@ -13,6 +13,7 @@
   - #4466, Fix undefined behaviour in _postgis_gserialized_stats (Raúl Marín)
   - #4209, Handle NULL geometry values in pgsql2shp (Paul Ramsey)
   - #4419, Use protobuf version to enable/disable mvt/geobuf (Paul Ramsey)
+  - #4437, Handle POINT EMPTY in shape loader/dumper (Paul Ramsey)
 
 
 PostGIS 2.4.7

Modified: branches/2.4/loader/pgsql2shp-core.c
===================================================================
--- branches/2.4/loader/pgsql2shp-core.c	2019-07-31 21:41:51 UTC (rev 17650)
+++ branches/2.4/loader/pgsql2shp-core.c	2019-07-31 21:41:58 UTC (rev 17651)
@@ -67,7 +67,18 @@
 /** @brief Binary to hexewkb conversion function */
 char *convert_bytes_to_hex(uint8_t *ewkb, size_t size);
 
+static SHPObject *
+create_point_empty(SHPDUMPERSTATE *state, LWPOINT *lwpoint)
+{
+	SHPObject *obj;
+	const uint8_t ndr_nan[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f};
+	double double_nan;
 
+	memcpy(&double_nan, ndr_nan, 8);
+	obj = SHPCreateObject(state->outshptype, -1, 0, NULL, NULL, 1, &double_nan, &double_nan, &double_nan, &double_nan);
+	return obj;
+}
+
 static SHPObject *
 create_point(SHPDUMPERSTATE *state, LWPOINT *lwpoint)
 {
@@ -2108,7 +2119,14 @@
 			switch (lwgeom->type)
 			{
 			case POINTTYPE:
-				obj = create_point(state, lwgeom_as_lwpoint(lwgeom));
+				if (lwgeom_is_empty(lwgeom))
+				{
+					obj = create_point_empty(state, lwgeom_as_lwpoint(lwgeom));
+				}
+				else
+				{
+					obj = create_point(state, lwgeom_as_lwpoint(lwgeom));
+				}
 				break;
 
 			case MULTIPOINTTYPE:

Modified: branches/2.4/loader/shp2pgsql-core.c
===================================================================
--- branches/2.4/loader/shp2pgsql-core.c	2019-07-31 21:41:51 UTC (rev 17650)
+++ branches/2.4/loader/shp2pgsql-core.c	2019-07-31 21:41:58 UTC (rev 17651)
@@ -240,42 +240,51 @@
 	FLAGS_SET_Z(dims, state->has_z);
 	FLAGS_SET_M(dims, state->has_m);
 
-	/* Allocate memory for our array of LWPOINTs and our dynptarrays */
-	lwmultipoints = malloc(sizeof(LWPOINT *) * obj->nVertices);
-
-	/* We need an array of pointers to each of our sub-geometries */
-	for (u = 0; u < obj->nVertices; u++)
+	/* POINT EMPTY encoded as POINT(NaN NaN) */
+	if (obj->nVertices == 1 && isnan(obj->padfX[0]) && isnan(obj->padfY[0]))
 	{
-		/* Create a ptarray containing a single point */
-		POINTARRAY *pa = ptarray_construct_empty(state->has_z, state->has_m, 1);
+		lwgeom = lwpoint_as_lwgeom(lwpoint_construct_empty(state->from_srid, state->has_z, state->has_m));
+	}
+	/* Not empty */
+	else
+	{
+		/* Allocate memory for our array of LWPOINTs and our dynptarrays */
+		lwmultipoints = malloc(sizeof(LWPOINT *) * obj->nVertices);
 
-		/* Generate the point */
-		point4d.x = obj->padfX[u];
-		point4d.y = obj->padfY[u];
+		/* We need an array of pointers to each of our sub-geometries */
+		for (u = 0; u < obj->nVertices; u++)
+		{
+			/* Create a ptarray containing a single point */
+			POINTARRAY *pa = ptarray_construct_empty(state->has_z, state->has_m, 1);
 
-		if (state->has_z)
-			point4d.z = obj->padfZ[u];
-		if (state->has_m)
-			point4d.m = obj->padfM[u];
+			/* Generate the point */
+			point4d.x = obj->padfX[u];
+			point4d.y = obj->padfY[u];
 
-		/* Add in the point! */
-		ptarray_append_point(pa, &point4d, LW_TRUE);
+			if (state->has_z)
+				point4d.z = obj->padfZ[u];
+			if (state->has_m)
+				point4d.m = obj->padfM[u];
 
-		/* Generate the LWPOINT */
-		lwmultipoints[u] = lwpoint_as_lwgeom(lwpoint_construct(state->from_srid, NULL, pa));
-	}
+			/* Add in the point! */
+			ptarray_append_point(pa, &point4d, LW_TRUE);
 
-	/* If we have more than 1 vertex then we are working on a MULTIPOINT and so generate a MULTIPOINT
-	rather than a POINT */
-	if ((obj->nVertices > 1) || force_multi)
-	{
-		lwgeom = lwcollection_as_lwgeom(lwcollection_construct(MULTIPOINTTYPE, state->from_srid, NULL, obj->nVertices, lwmultipoints));
+			/* Generate the LWPOINT */
+			lwmultipoints[u] = lwpoint_as_lwgeom(lwpoint_construct(state->from_srid, NULL, pa));
+		}
+
+		/* If we have more than 1 vertex then we are working on a MULTIPOINT and so generate a MULTIPOINT
+		rather than a POINT */
+		if ((obj->nVertices > 1) || force_multi)
+		{
+			lwgeom = lwcollection_as_lwgeom(lwcollection_construct(MULTIPOINTTYPE, state->from_srid, NULL, obj->nVertices, lwmultipoints));
+		}
+		else
+		{
+			lwgeom = lwmultipoints[0];
+			lwfree(lwmultipoints);
+		}
 	}
-	else
-	{
-		lwgeom = lwmultipoints[0];
-		lwfree(lwmultipoints);
-	}
 
 	if (state->config->use_wkt)
 	{



More information about the postgis-tickets mailing list