From 3113a946ef38e9430f7fc3d53c2b9957373badc0 Mon Sep 17 00:00:00 2001 From: Paul Ramsey Date: Wed, 31 Jul 2019 21:42:20 +0000 Subject: [PATCH] Handle POINT EMPTY in shape loader/dumper Closes #4437 git-svn-id: http://svn.osgeo.org/postgis/trunk@17653 b70326c6-7e19-0410-871a-916f4a2858ee --- NEWS | 1 + loader/pgsql2shp-core.c | 20 +++++++++++- loader/shp2pgsql-core.c | 67 +++++++++++++++++++++++------------------ 3 files changed, 58 insertions(+), 30 deletions(-) diff --git a/NEWS b/NEWS index a728f4d8f..dd959d87b 100644 --- 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 diff --git a/loader/pgsql2shp-core.c b/loader/pgsql2shp-core.c index 1b0a650c1..d486edc94 100644 --- a/loader/pgsql2shp-core.c +++ b/loader/pgsql2shp-core.c @@ -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: diff --git a/loader/shp2pgsql-core.c b/loader/shp2pgsql-core.c index dc71310eb..c37e3509e 100644 --- a/loader/shp2pgsql-core.c +++ b/loader/shp2pgsql-core.c @@ -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) -- 2.40.0