]> granicus.if.org Git - postgis/commitdiff
Handle POINT EMPTY in shape loader/dumper
authorPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 31 Jul 2019 21:42:20 +0000 (21:42 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 31 Jul 2019 21:42:20 +0000 (21:42 +0000)
Closes #4437

git-svn-id: http://svn.osgeo.org/postgis/trunk@17653 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
loader/pgsql2shp-core.c
loader/shp2pgsql-core.c

diff --git a/NEWS b/NEWS
index a728f4d8fb59145fe51cb05a8b679e46f20fcc4d..dd959d87b8d70d9216944785a2fafe9e6e89b599 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,7 @@ Additional features enabled if you are running Proj6+ and PostgreSQL 12
   - #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 3.0.0alpha3
 2019/07/01
index 1b0a650c1e679ac4078856ee207b81780137859e..d486edc94ad9abf4b74009af5fc7af0fbfcc21ba 100644 (file)
@@ -67,6 +67,17 @@ static char * goodDBFValue(char *in, char fieldType);
 /** @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)
@@ -2112,7 +2123,14 @@ int ShpLoaderGenerateShapeRow(SHPDUMPERSTATE *state)
                        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:
index dc71310eb87754d3959542a305436d12eaa99398..c37e3509eb545d6a36b01a7f1b2c4babbb558c54 100644 (file)
@@ -240,41 +240,50 @@ GeneratePointGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry, in
        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]))
+       {
+               lwgeom = lwpoint_as_lwgeom(lwpoint_construct_empty(state->from_srid, state->has_z, state->has_m));
+       }
+       /* Not empty */
+       else
        {
-               /* Create a ptarray containing a single point */
-               POINTARRAY *pa = ptarray_construct_empty(state->has_z, state->has_m, 1);
+               /* 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));
-       }
-       else
-       {
-               lwgeom = lwmultipoints[0];
-               lwfree(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);
+               }
        }
 
        if (state->config->use_wkt)