From: Darafei Praliaskouski Date: Fri, 12 Jan 2018 08:48:50 +0000 (+0000) Subject: Encoded Polyline of EMPTY X-Git-Tag: 2.4.3rc1~12 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b998fe3440b3316c31117a9392bf1f068a291433;p=postgis Encoded Polyline of EMPTY Pull in from trunk Closes #3982 git-svn-id: http://svn.osgeo.org/postgis/branches/2.4@16264 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index d6663b39f..9c713fd1f 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,9 @@ PostGIS 2.4.3 - #3965, ST_ClusterKMeans used to lose some clusters on initialization (Darafei Praliaskouski) - #3956, Brin opclass object does not upgrade properly (Sandro Santilli) + - #3982, ST_AsEncodedPolyline supports LINESTRING EMPTY and MULTIPOINT EMPTY + (Darafei Praliaskouski) + * Enhancements * - #3944, Update to EPSG register v9.2 (Even Rouault) diff --git a/liblwgeom/cunit/cu_out_encoded_polyline.c b/liblwgeom/cunit/cu_out_encoded_polyline.c index 95c12e941..0cdcc1f59 100644 --- a/liblwgeom/cunit/cu_out_encoded_polyline.c +++ b/liblwgeom/cunit/cu_out_encoded_polyline.c @@ -1,15 +1,15 @@ /********************************************************************** -* -* PostGIS - Spatial Types for PostgreSQL -* http://postgis.net -* -* Copyright 2014 Kashif Rasul and -* Shoaib Burq -* -* This is free software; you can redistribute and/or modify it under -* the terms of the GNU General Public Licence. See the COPYING file. -* -**********************************************************************/ + * + * PostGIS - Spatial Types for PostgreSQL + * http://postgis.net + * + * Copyright 2014 Kashif Rasul and + * Shoaib Burq + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU General Public Licence. See the COPYING file. + * + **********************************************************************/ #include #include @@ -19,10 +19,11 @@ #include "liblwgeom_internal.h" #include "cu_tester.h" -static void do_encoded_polyline_test(char * in, int precision, char * out) +static void +do_encoded_polyline_test(char* in, int precision, char* out) { - LWGEOM *g; - char * h; + LWGEOM* g; + char* h; g = lwgeom_from_wkt(in, LW_PARSER_CHECK_NONE); h = lwgeom_to_encoded_polyline(g, precision); @@ -36,66 +37,65 @@ static void do_encoded_polyline_test(char * in, int precision, char * out) lwfree(h); } - -static void out_encoded_polyline_test_geoms(void) +static void +out_encoded_polyline_test_geoms(void) { /* Magic Linestring */ do_encoded_polyline_test( - "SRID=4326;LINESTRING(33.6729 38.7071,33.6692 38.701,33.6673 38.6972,33.6626 38.6871)", - 5, - "k~fkFsvolEbe@bVvVzJb~@j\\"); - return; + "SRID=4326;LINESTRING(33.6729 38.7071,33.6692 38.701," + "33.6673 38.6972,33.6626 38.6871)", + 5, + "k~fkFsvolEbe@bVvVzJb~@j\\"); /* Linestring */ do_encoded_polyline_test( - "LINESTRING(-120.2 38.5,-120.95 40.7,-126.453 43.252)", - 5, - "_p~iF~ps|U_ulLnnqC_mqNvxq`@"); + "LINESTRING(-120.2 38.5,-120.95 40.7,-126.453 43.252)", + 5, + "_p~iF~ps|U_ulLnnqC_mqNvxq`@"); + do_encoded_polyline_test("LINESTRING EMPTY", 5, ""); /* MultiPoint */ do_encoded_polyline_test( - "MULTIPOINT(-120.2 38.5,-120.95 40.7)", - 5, - "_p~iF~ps|U_ulLnnqC"); + "MULTIPOINT(-120.2 38.5,-120.95 40.7)", 5, "_p~iF~ps|U_ulLnnqC"); + do_encoded_polyline_test("MULTIPOINT EMPTY", 5, ""); } -static void out_encoded_polyline_test_srid(void) +static void +out_encoded_polyline_test_srid(void) { /* SRID - with PointArray */ do_encoded_polyline_test( - "SRID=4326;LINESTRING(0 1,2 3)", - 5, - "_ibE?_seK_seK"); + "SRID=4326;LINESTRING(0 1,2 3)", 5, "_ibE?_seK_seK"); /* wrong SRID */ do_encoded_polyline_test( - "SRID=4327;LINESTRING(0 1,2 3)", - 5, - "_ibE?_seK_seK"); + "SRID=4327;LINESTRING(0 1,2 3)", 5, "_ibE?_seK_seK"); } -static void out_encoded_polyline_test_precision(void) +static void +out_encoded_polyline_test_precision(void) { /* Linestring */ do_encoded_polyline_test( - "LINESTRING(-0.250691 49.283048,-0.250633 49.283376,-0.250502 49.283972,-0.251245 49.284028,-0.251938 49.284232,-0.251938 49.2842)", - 6, - "o}~~|AdshNoSsBgd@eGoBlm@wKhj@~@?"); + "LINESTRING(-0.250691 49.283048, -0.250633 49.283376," + "-0.250502 49.283972, -0.251245 49.284028, -0.251938 " + "49.284232, -0.251938 49.2842)", + 6, + "o}~~|AdshNoSsBgd@eGoBlm@wKhj@~@?"); /* MultiPoint */ do_encoded_polyline_test( - "MULTIPOINT(-120.2 38.5,-120.95 40.7)", - 3, - "gejAnwiFohCzm@"); + "MULTIPOINT(-120.2 38.5,-120.95 40.7)", 3, "gejAnwiFohCzm@"); } /* ** Used by test harness to register the tests in this file. */ void out_encoded_polyline_suite_setup(void); -void out_encoded_polyline_suite_setup(void) +void +out_encoded_polyline_suite_setup(void) { CU_pSuite suite = CU_add_suite("encoded_polyline_output", NULL, NULL); PG_ADD_TEST(suite, out_encoded_polyline_test_geoms); diff --git a/liblwgeom/lwout_encoded_polyline.c b/liblwgeom/lwout_encoded_polyline.c index 2f3a4aa3f..011da60ac 100644 --- a/liblwgeom/lwout_encoded_polyline.c +++ b/liblwgeom/lwout_encoded_polyline.c @@ -18,21 +18,21 @@ * ********************************************************************** * -* Copyright 2014 Kashif Rasul and + * Copyright 2014 Kashif Rasul and + * Shoaib Burq * **********************************************************************/ - #include "stringbuffer.h" #include "liblwgeom_internal.h" -static char * lwline_to_encoded_polyline(const LWLINE*, int precision); -static char * lwmmpoint_to_encoded_polyline(const LWMPOINT*, int precision); -static char * pointarray_to_encoded_polyline(const POINTARRAY*, int precision); +static char* lwline_to_encoded_polyline(const LWLINE*, int precision); +static char* lwmmpoint_to_encoded_polyline(const LWMPOINT*, int precision); +static char* pointarray_to_encoded_polyline(const POINTARRAY*, int precision); /* takes a GEOMETRY and returns an Encoded Polyline representation */ -extern char * -lwgeom_to_encoded_polyline(const LWGEOM *geom, int precision) +extern char* +lwgeom_to_encoded_polyline(const LWGEOM* geom, int precision) { int type = geom->type; switch (type) @@ -42,53 +42,66 @@ lwgeom_to_encoded_polyline(const LWGEOM *geom, int precision) case MULTIPOINTTYPE: return lwmmpoint_to_encoded_polyline((LWMPOINT*)geom, precision); default: - lwerror("lwgeom_to_encoded_polyline: '%s' geometry type not supported", lwtype_name(type)); + lwerror("lwgeom_to_encoded_polyline: '%s' geometry type not supported", + lwtype_name(type)); return NULL; } } -static -char * lwline_to_encoded_polyline(const LWLINE *line, int precision) +static char* +lwline_to_encoded_polyline(const LWLINE* line, int precision) { return pointarray_to_encoded_polyline(line->points, precision); } -static -char * lwmmpoint_to_encoded_polyline(const LWMPOINT *mpoint, int precision) +static char* +lwmmpoint_to_encoded_polyline(const LWMPOINT* mpoint, int precision) { - LWLINE *line = lwline_from_lwmpoint(mpoint->srid, mpoint); - char *encoded_polyline = lwline_to_encoded_polyline(line, precision); + LWLINE* line = lwline_from_lwmpoint(mpoint->srid, mpoint); + char* encoded_polyline = lwline_to_encoded_polyline(line, precision); lwline_free(line); return encoded_polyline; } -static -char * pointarray_to_encoded_polyline(const POINTARRAY *pa, int precision) +static char* +pointarray_to_encoded_polyline(const POINTARRAY* pa, int precision) { int i; - const POINT2D *prevPoint; - int *delta = lwalloc(2*sizeof(int)*pa->npoints); - char *encoded_polyline = NULL; - stringbuffer_t *sb; - double scale = pow(10,precision); + const POINT2D* prevPoint; + int* delta; + char* encoded_polyline = NULL; + stringbuffer_t* sb; + double scale = pow(10, precision); + + /* Empty input is empty string */ + if (pa->npoints == 0) { + encoded_polyline = lwalloc(1 * sizeof(char)); + encoded_polyline[0] = 0; + return encoded_polyline; + } + + delta = lwalloc(2 * sizeof(int) * pa->npoints); - /* Take the double value and multiply it by 1x10^precision, rounding the result */ + /* Take the double value and multiply it by 1x10^precision, rounding the + * result */ prevPoint = getPoint2d_cp(pa, 0); - delta[0] = round(prevPoint->y*scale); - delta[1] = round(prevPoint->x*scale); + delta[0] = round(prevPoint->y * scale); + delta[1] = round(prevPoint->x * scale); - /* points only include the offset from the previous point */ - for (i=1; inpoints; i++) + /* Points only include the offset from the previous point */ + for (i = 1; i < pa->npoints; i++) { - const POINT2D *point = getPoint2d_cp(pa, i); - delta[2*i] = round(point->y*scale) - round(prevPoint->y*scale); - delta[(2*i)+1] = round(point->x*scale) - round(prevPoint->x*scale); + const POINT2D* point = getPoint2d_cp(pa, i); + delta[2 * i] = round(point->y * scale) - round(prevPoint->y * scale); + delta[(2 * i) + 1] = + round(point->x * scale) - round(prevPoint->x * scale); prevPoint = point; } - /* value to binary: a negative value must be calculated using its two's complement */ - for (i=0; inpoints*2; i++) + /* value to binary: a negative value must be calculated using its two's + * complement */ + for (i = 0; i < pa->npoints * 2; i++) { /* Multiply by 2 for a signed left shift */ delta[i] *= 2; @@ -99,11 +112,12 @@ char * pointarray_to_encoded_polyline(const POINTARRAY *pa, int precision) } sb = stringbuffer_create(); - for (i=0; inpoints*2; i++) + for (i = 0; i < pa->npoints * 2; i++) { int numberToEncode = delta[i]; - while (numberToEncode >= 0x20) { + while (numberToEncode >= 0x20) + { /* Place the 5-bit chunks into reverse order or each value with 0x20 if another bit chunk follows and add 63*/ int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63;