From: Paul Ramsey Date: Thu, 25 Jun 2015 20:07:31 +0000 (+0000) Subject: #3181, Output POINT EMPTY in WKB using NaN as coordinate values X-Git-Tag: 2.2.0rc1~329 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d47d1be63ab8a10e6229926e0a6a3c52cbd9c5ef;p=postgis #3181, Output POINT EMPTY in WKB using NaN as coordinate values git-svn-id: http://svn.osgeo.org/postgis/trunk@13707 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index 0fba1aa1a..b17d9ff3f 100644 --- a/NEWS +++ b/NEWS @@ -14,6 +14,7 @@ PostGIS 2.2.0 - #2567, ST_Count(tablename, rastercolumn, ...) uses ST_CountAgg() - By default, PostGIS raster disables all GDAL drivers affecting out-db rasters, ST_FromGDALRaster() and ST_AsGDALRaster() variants + - #3181, POINT EMPTY is now stored as POINT(NaN NaN) in WKB, instead of as MULTIPOINT EMPTY * Deprecated signatures * diff --git a/liblwgeom/cunit/cu_in_wkb.c b/liblwgeom/cunit/cu_in_wkb.c index 0000a0688..19c21d7ce 100644 --- a/liblwgeom/cunit/cu_in_wkb.c +++ b/liblwgeom/cunit/cu_in_wkb.c @@ -109,8 +109,23 @@ static void test_wkb_in_point(void) CU_ASSERT_STRING_EQUAL(hex_a, hex_b); cu_wkb_in("SRID=4;POINTM(1 1 1)"); -// printf("old: %s\nnew: %s\n",hex_a, hex_b); CU_ASSERT_STRING_EQUAL(hex_a, hex_b); + + cu_wkb_in("POINT EMPTY"); + CU_ASSERT_STRING_EQUAL(hex_a, hex_b); + + cu_wkb_in("SRID=4326;POINT EMPTY"); + CU_ASSERT_STRING_EQUAL(hex_a, hex_b); + + cu_wkb_in("POINT Z EMPTY"); + CU_ASSERT_STRING_EQUAL(hex_a, hex_b); + + cu_wkb_in("POINT M EMPTY"); + CU_ASSERT_STRING_EQUAL(hex_a, hex_b); + + cu_wkb_in("POINT ZM EMPTY"); + CU_ASSERT_STRING_EQUAL(hex_a, hex_b); + } static void test_wkb_in_linestring(void) diff --git a/liblwgeom/cunit/cu_libgeom.c b/liblwgeom/cunit/cu_libgeom.c index ea707cecf..8d27a4aaa 100644 --- a/liblwgeom/cunit/cu_libgeom.c +++ b/liblwgeom/cunit/cu_libgeom.c @@ -240,7 +240,6 @@ static void test_gbox_serialized_size(void) - static void test_lwgeom_from_gserialized(void) { LWGEOM *geom; diff --git a/liblwgeom/cunit/cu_out_wkb.c b/liblwgeom/cunit/cu_out_wkb.c index 1df0aae6c..8094f87b5 100644 --- a/liblwgeom/cunit/cu_out_wkb.c +++ b/liblwgeom/cunit/cu_out_wkb.c @@ -73,6 +73,21 @@ static void test_wkb_out_point(void) cu_wkb("SRID=4;POINTM(1 1 1)"); CU_ASSERT_STRING_EQUAL(s,"0060000001000000043FF00000000000003FF00000000000003FF0000000000000"); + + cu_wkb("POINT EMPTY"); + CU_ASSERT_STRING_EQUAL(s,"00000000017FF80000000000007FF8000000000000"); + + cu_wkb("SRID=4326;POINT EMPTY"); + CU_ASSERT_STRING_EQUAL(s,"0020000001000010E67FF80000000000007FF8000000000000"); + + cu_wkb("POINT Z EMPTY"); + CU_ASSERT_STRING_EQUAL(s,"00800000017FF80000000000007FF80000000000007FF8000000000000"); + + cu_wkb("POINT M EMPTY"); + CU_ASSERT_STRING_EQUAL(s,"00400000017FF80000000000007FF80000000000007FF8000000000000"); + + cu_wkb("POINT ZM EMPTY"); + CU_ASSERT_STRING_EQUAL(s,"00C00000017FF80000000000007FF80000000000007FF80000000000007FF8000000000000"); } static void test_wkb_out_linestring(void) diff --git a/liblwgeom/lwin_wkb.c b/liblwgeom/lwin_wkb.c index 5a90520d6..ba09e720b 100644 --- a/liblwgeom/lwin_wkb.c +++ b/liblwgeom/lwin_wkb.c @@ -11,6 +11,7 @@ #include "liblwgeom_internal.h" #include "lwgeom_log.h" +#include /** * Used for passing the parse state between the parsing functions. @@ -369,6 +370,7 @@ static LWPOINT* lwpoint_from_wkb_state(wkb_parse_state *s) POINTARRAY *pa = NULL; size_t pa_size; uint32_t ndims = 2; + const POINT2D *pt; /* Count the dimensions. */ if( s->has_z ) ndims++; @@ -397,7 +399,16 @@ static LWPOINT* lwpoint_from_wkb_state(wkb_parse_state *s) } } - return lwpoint_construct(s->srid, NULL, pa); + /* Check for POINT(NaN NaN) ==> POINT EMPTY */ + pt = getPoint2d_cp(pa, 0); + if ( isnan(pt->x) && isnan(pt->y) ) + { + return lwpoint_construct_empty(s->srid, s->has_z, s->has_m); + } + else + { + return lwpoint_construct(s->srid, NULL, pa); + } } /** diff --git a/liblwgeom/lwout_wkb.c b/liblwgeom/lwout_wkb.c index f4722ecd4..dc1aa6863 100644 --- a/liblwgeom/lwout_wkb.c +++ b/liblwgeom/lwout_wkb.c @@ -9,6 +9,8 @@ * **********************************************************************/ +#include + #include "liblwgeom_internal.h" #include "lwgeom_log.h" @@ -274,11 +276,25 @@ static uint8_t* double_to_wkb_buf(const double d, uint8_t *buf, uint8_t variant) */ static size_t empty_to_wkb_size(const LWGEOM *geom, uint8_t variant) { - size_t size = WKB_BYTE_SIZE + WKB_INT_SIZE + WKB_INT_SIZE; + /* endian byte + type integer */ + size_t size = WKB_BYTE_SIZE + WKB_INT_SIZE; + /* optional srid integer */ if ( lwgeom_wkb_needs_srid(geom, variant) ) size += WKB_INT_SIZE; + /* Represent POINT EMPTY as POINT(NaN NaN) */ + if ( geom->type == POINTTYPE ) + { + const LWPOINT *pt = (LWPOINT*)geom; + size += WKB_DOUBLE_SIZE * FLAGS_NDIMS(pt->point->flags); + } + /* num-elements */ + else + { + size += WKB_INT_SIZE; + } + return size; } @@ -286,13 +302,6 @@ static uint8_t* empty_to_wkb_buf(const LWGEOM *geom, uint8_t *buf, uint8_t varia { uint32_t wkb_type = lwgeom_wkb_type(geom, variant); - if ( geom->type == POINTTYPE ) - { - /* Change POINT to MULTIPOINT */ - wkb_type &= ~WKB_POINT_TYPE; /* clear POINT flag */ - wkb_type |= WKB_MULTIPOINT_TYPE; /* set MULTIPOINT flag */ - } - /* Set the endian flag */ buf = endian_to_wkb_buf(buf, variant); @@ -303,8 +312,24 @@ static uint8_t* empty_to_wkb_buf(const LWGEOM *geom, uint8_t *buf, uint8_t varia if ( lwgeom_wkb_needs_srid(geom, variant) ) buf = integer_to_wkb_buf(geom->srid, buf, variant); - /* Set nrings/npoints/ngeoms to zero */ - buf = integer_to_wkb_buf(0, buf, variant); + /* Represent POINT EMPTY as POINT(NaN NaN) */ + if ( geom->type == POINTTYPE ) + { + const LWPOINT *pt = (LWPOINT*)geom; + static double nn = NAN; + int i; + for ( i = 0; i < FLAGS_NDIMS(pt->point->flags); i++ ) + { + buf = double_to_wkb_buf(nn, buf, variant); + } + } + /* Everything else is flagged as empty using num-elements == 0 */ + else + { + /* Set nrings/npoints/ngeoms to zero */ + buf = integer_to_wkb_buf(0, buf, variant); + } + return buf; }