From 9df7101d933c7c9b853030b3c899756ad37e987d Mon Sep 17 00:00:00 2001 From: Sandro Santilli Date: Fri, 9 Dec 2011 13:50:50 +0000 Subject: [PATCH] Fix segfault in GML3 extent output (#1323) Add support for srsDimension in GML3 extent output. Add unit level comprensive regression testing. git-svn-id: http://svn.osgeo.org/postgis/trunk@8333 b70326c6-7e19-0410-871a-916f4a2858ee --- liblwgeom/cunit/cu_out_gml.c | 175 +++++++++++++++++++++++++++++++++++ liblwgeom/lwout_gml.c | 110 +++++++++++----------- 2 files changed, 232 insertions(+), 53 deletions(-) diff --git a/liblwgeom/cunit/cu_out_gml.c b/liblwgeom/cunit/cu_out_gml.c index 92b873a8b..3bb47725a 100644 --- a/liblwgeom/cunit/cu_out_gml.c +++ b/liblwgeom/cunit/cu_out_gml.c @@ -168,6 +168,46 @@ static void do_gml3_unsupported(char * in, char * out) lwgeom_free(g); } +static void do_gml2_extent_test(char * in, char * out, char * srs, + double precision, char * prefix) +{ + LWGEOM *g; + char *h; + + g = lwgeom_from_wkt(in, LW_PARSER_CHECK_NONE); + h = lwgeom_extent_to_gml2(g, srs, precision, prefix); + if ( ! h ) h = cu_error_msg; + + if (strcmp(h, out)) + fprintf(stderr, "\nEXT GML 2 - In: %s\nObt: %s\nExp: %s\n", + in, h, out); + CU_ASSERT_STRING_EQUAL(out, h); + cu_error_msg_reset(); + + lwfree(h); + lwgeom_free(g); +} + +static void do_gml3_extent_test(char * in, char * out, char * srs, + double precision, int opts, char* prefix) +{ + LWGEOM *g; + char *h; + + g = lwgeom_from_wkt(in, LW_PARSER_CHECK_NONE); + h = lwgeom_extent_to_gml3(g, srs, precision, opts, prefix); + if ( ! h ) h = cu_error_msg; + + if (strcmp(h, out)) + fprintf(stderr, "\nEXT GML 3 - In: %s\nObt: %s\nExp: %s\n", + in, h, out); + CU_ASSERT_STRING_EQUAL(out, h); + cu_error_msg_reset(); + + lwfree(h); + lwgeom_free(g); +} + static void out_gml_test_precision(void) { @@ -945,6 +985,139 @@ static void out_gml_test_geoms_nodims(void) NULL, 0, 0, 0, ""); } +static void out_gml2_extent(void) +{ + /* GML2: Point */ + do_gml2_extent_test( + "POINT(-15 60)", + "-15,60 -15,60", + NULL, 15, ""); + do_gml2_extent_test( + "POINT(-15 60)", + "-15,60 -15,60", + NULL, 15, "gml:"); + do_gml2_extent_test( + "POINT(-15 60)", + "-15,60 -15,60", + "urn:ogc:def:crs:EPSG::4326", 15, ""); + + /* GML2: Multipoint */ + do_gml2_extent_test( + "MULTIPOINT(2 3, -5 -6)", + "-5,-6 2,3", + NULL, 15, ""); + + /* GML2: Linestring */ + do_gml2_extent_test( + "LINESTRING(0 1,2 3,4 5)", + "0,1 4,5", + NULL, 15, ""); + + /* GML2: MultiLinestring */ + do_gml2_extent_test( + "MULTILINESTRING((0 1,2 3),(4 5, 10 6))", + "0,1 10,6", + NULL, 15, ""); + + /* GML2: Polygon */ + do_gml2_extent_test( + "POLYGON((1 7,7 14, 14 7, 1 7))", + "1,7 14,14", + NULL, 15, ""); + + /* GML2: MultiPolygon */ + do_gml2_extent_test( + "MULTIPOLYGON(((1 7,7 14, 14 7, 1 7)),((-4 -6, -15 3, 0 0, -4 -6))))", + "-15,-6 14,14", + NULL, 15, ""); + + /* GML2: MultiSurface */ + do_gml2_extent_test( + "MULTISURFACE(CURVEPOLYGON(CIRCULARSTRING(-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0 0.5,1 0,0 1,-1 0)),((7 8,10 10,6 14,4 11,7 8)))", + "-2,-1 10,14", + NULL, 15, ""); + + /* GML2: empty (FIXME) */ + do_gml2_extent_test( + "GEOMETRYCOLLECTION EMPTY", + "0,0 0,0", + NULL, 15, ""); + +} + +static void out_gml3_extent(void) +{ + /* GML3: Point */ + do_gml3_extent_test( + "POINT(-15 60)", + "-15 60-15 60", + NULL, 15, 0, ""); + do_gml3_extent_test( + "POINT(-15 60)", + "-15 60-15 60", + NULL, 15, 0, "gml:"); + do_gml3_extent_test( + "POINT(-15 60)", + "-15 60-15 60", + "urn:ogc:def:crs:EPSG::4326", 15, 0, ""); + + /* GML3: Multipoint */ + do_gml3_extent_test( + "MULTIPOINT(2 3, -5 -6)", + "-5 -62 3", + NULL, 15, 0, ""); + + /* GML3: Linestring */ + do_gml3_extent_test( + "LINESTRING(0 1,2 3,4 5)", + "0 14 5", + NULL, 15, 0, ""); + + /* GML3: MultiLinestring */ + do_gml3_extent_test( + "MULTILINESTRING((0 1,2 3),(4 5, 10 6))", + "0 110 6", + NULL, 15, 0, ""); + do_gml3_extent_test( + "MULTILINESTRING((0 1,2 3),(4 5, 10 6))", + "1 06 10", + NULL, 15, LW_GML_IS_DEGREE, ""); + do_gml3_extent_test( + "MULTILINESTRING((0 1,2 3),(4 5, 10 6))", + "1 06 10", + NULL, 15, LW_GML_IS_DEGREE|LW_GML_IS_DIMS, ""); + do_gml3_extent_test( + "MULTILINESTRING((0 1 10,2 3 30),(4 5 50, 10 6 -70))", + "1 0 -706 10 50", + NULL, 15, LW_GML_IS_DEGREE|LW_GML_IS_DIMS, ""); + + /* GML3: Polygon */ + do_gml3_extent_test( + "POLYGON((1 7,7 14, 14 7, 1 7))", + "1 714 14", + NULL, 15, 0, ""); + + /* GML3: MultiPolygon */ + do_gml3_extent_test( + "MULTIPOLYGON(((1 7,7 14, 14 7, 1 7)),((-4 -6, -15 3, 0 0, -4 -6))))", + "-15 -614 14", + NULL, 15, 0, ""); + + /* GML3: MultiSurface */ + do_gml3_extent_test( + "MULTISURFACE(CURVEPOLYGON(CIRCULARSTRING(-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0 0.5,1 0,0 1,-1 0)),((7 8,10 10,6 14,4 11,7 8)))", + "-2 -110 14", + NULL, 15, 0, ""); + + /* GML3: empty (FIXME) */ + do_gml3_extent_test( + "GEOMETRYCOLLECTION EMPTY", + "0 00 0", + NULL, 15, 0, ""); + +} + + /* @@ -959,6 +1132,8 @@ CU_TestInfo out_gml_tests[] = PG_TEST(out_gml_test_geoms), PG_TEST(out_gml_test_geoms_prefix), PG_TEST(out_gml_test_geoms_nodims), + PG_TEST(out_gml2_extent), + PG_TEST(out_gml3_extent), CU_TEST_INFO_NULL }; CU_SuiteInfo out_gml_suite = {"GML Out Suite", NULL, NULL, out_gml_tests}; diff --git a/liblwgeom/lwout_gml.c b/liblwgeom/lwout_gml.c index ccc7d5254..2b2c15199 100644 --- a/liblwgeom/lwout_gml.c +++ b/liblwgeom/lwout_gml.c @@ -53,10 +53,16 @@ static size_t pointArray_toGML3(POINTARRAY *pa, char *buf, int precision, int op static size_t pointArray_GMLsize(POINTARRAY *pa, int precision); +static const GBOX * +lwgeom_get_bbox(const LWGEOM *lwg) +{ + /* if ( ! lwg->bbox ) lwnotice("Adding a bbox"); */ + lwgeom_add_bbox((LWGEOM *)lwg); /* adds one if not already there */ + return lwg->bbox; +} - -extern char * -lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix) +static char * +gbox_to_gml2(const GBOX *bbox, const char *srs, int precision, const char *prefix) { int size; POINT4D pt; @@ -64,32 +70,16 @@ lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *ptr, *output; size_t prefixlen = strlen(prefix); - switch (geom->type) - { - case POINTTYPE: - case LINETYPE: - case POLYGONTYPE: - case MULTIPOINTTYPE: - case MULTILINETYPE: - case MULTIPOLYGONTYPE: - case COLLECTIONTYPE: - break; - - default: - lwerror("lwgeom_extent_to_gml2: '%s' geometry type not supported", lwtype_name(geom->type)); - return NULL; - } - - pa = ptarray_construct_empty(FLAGS_GET_Z(geom->flags), 0, 2); + pa = ptarray_construct_empty(FLAGS_GET_Z(bbox->flags), 0, 2); - pt.x = geom->bbox->xmin; - pt.y = geom->bbox->ymin; - if (FLAGS_GET_Z(geom->flags)) pt.z = geom->bbox->zmin; + pt.x = bbox->xmin; + pt.y = bbox->ymin; + if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmin; ptarray_append_point(pa, &pt, LW_TRUE); - pt.x = geom->bbox->xmax; - pt.y = geom->bbox->ymax; - if (FLAGS_GET_Z(geom->flags)) pt.z = geom->bbox->zmax; + pt.x = bbox->xmax; + pt.y = bbox->ymax; + if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmax; ptarray_append_point(pa, &pt, LW_TRUE); size = pointArray_GMLsize(pa, precision); @@ -109,57 +99,46 @@ lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const return output; } - -extern char * -lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix) +static char * +gbox_to_gml3(const GBOX *bbox, const char *srs, int precision, int opts, const char *prefix) { int size; POINT4D pt; POINTARRAY *pa; char *ptr, *output; size_t prefixlen = strlen(prefix); + int dimension = 2; - switch (geom->type) - { - case POINTTYPE: - case LINETYPE: - case POLYGONTYPE: - case MULTIPOINTTYPE: - case MULTILINETYPE: - case MULTIPOLYGONTYPE: - case COLLECTIONTYPE: - break; - - default: - lwerror("lwgeom_extent_to_gml3: '%s' geometry type not supported", lwtype_name(geom->type)); - return NULL; - } + if (FLAGS_GET_Z(bbox->flags)) dimension = 3; - pa = ptarray_construct_empty(FLAGS_GET_Z(geom->flags), 0, 1); + pa = ptarray_construct_empty(FLAGS_GET_Z(bbox->flags), 0, 1); - pt.x = geom->bbox->xmin; - pt.y = geom->bbox->ymin; - if (FLAGS_GET_Z(geom->flags)) pt.z = geom->bbox->zmin; + pt.x = bbox->xmin; + pt.y = bbox->ymin; + if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmin; ptarray_append_point(pa, &pt, LW_TRUE); size = pointArray_GMLsize(pa, precision) * 2; size += ( sizeof("//") + (prefixlen*3) ) * 2; if ( srs ) size += strlen(srs) + sizeof(" srsName=.."); + if ( IS_DIMS(opts) ) size += sizeof(" srsDimension=. ."); ptr = output = lwalloc(size); - if ( srs ) ptr += sprintf(ptr, "<%sEnvelope srsName=\"%s\">", prefix, srs); - else ptr += sprintf(ptr, "<%sEnvelope>", prefix); + ptr += sprintf(ptr, "<%sEnvelope", prefix); + if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); + if ( IS_DIMS(opts) ) ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension); + ptr += sprintf(ptr, ">"); ptr += sprintf(ptr, "<%slowerCorner>", prefix); ptr += pointArray_toGML3(pa, ptr, precision, opts); ptr += sprintf(ptr, "", prefix); ptarray_remove_point(pa, 0); - pt.x = geom->bbox->xmax; - pt.y = geom->bbox->ymax; - if (FLAGS_GET_Z(geom->flags)) pt.z = geom->bbox->zmax; + pt.x = bbox->xmax; + pt.y = bbox->ymax; + if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmax; ptarray_append_point(pa, &pt, LW_TRUE); ptr += sprintf(ptr, "<%supperCorner>", prefix); @@ -172,6 +151,31 @@ lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int op return output; } + + +extern char * +lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix) +{ + const GBOX* bbox = lwgeom_get_bbox(geom); + if ( ! bbox ) { + lwerror("lwgeom_extent_to_gml2: empty geometry doesn't have a bounding box"); + return NULL; + } + char *ret = gbox_to_gml2(bbox, srs, precision, prefix); + return ret; +} + + +extern char * +lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix) +{ + const GBOX* bbox = lwgeom_get_bbox(geom); + if ( ! bbox ) { + lwerror("lwgeom_extent_to_gml3: empty geometry doesn't have a bounding box"); + return NULL; + } + return gbox_to_gml3(bbox, srs, precision, opts, prefix); +} /** -- 2.40.0