]> granicus.if.org Git - postgis/commitdiff
Fix segfault in GML3 extent output (#1323)
authorSandro Santilli <strk@keybit.net>
Fri, 9 Dec 2011 13:50:50 +0000 (13:50 +0000)
committerSandro Santilli <strk@keybit.net>
Fri, 9 Dec 2011 13:50:50 +0000 (13:50 +0000)
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
liblwgeom/lwout_gml.c

index 92b873a8b8ac2285fb1e653236a373e1199e0a1e..3bb47725acd6996b34a5557993a53ae256993827 100644 (file)
@@ -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)",
+           "<Box><coordinates>-15,60 -15,60</coordinates></Box>",
+           NULL, 15, "");
+       do_gml2_extent_test(
+           "POINT(-15 60)",
+           "<gml:Box><gml:coordinates>-15,60 -15,60</gml:coordinates></gml:Box>",
+           NULL, 15, "gml:");
+       do_gml2_extent_test(
+           "POINT(-15 60)",
+           "<Box srsName=\"urn:ogc:def:crs:EPSG::4326\"><coordinates>-15,60 -15,60</coordinates></Box>",
+           "urn:ogc:def:crs:EPSG::4326", 15, "");
+
+       /* GML2: Multipoint */
+       do_gml2_extent_test(
+           "MULTIPOINT(2 3, -5 -6)",
+           "<Box><coordinates>-5,-6 2,3</coordinates></Box>",
+           NULL, 15, "");
+
+       /* GML2: Linestring */
+       do_gml2_extent_test(
+           "LINESTRING(0 1,2 3,4 5)",
+           "<Box><coordinates>0,1 4,5</coordinates></Box>",
+           NULL, 15, "");
+
+       /* GML2: MultiLinestring */
+       do_gml2_extent_test(
+           "MULTILINESTRING((0 1,2 3),(4 5, 10 6))",
+           "<Box><coordinates>0,1 10,6</coordinates></Box>",
+           NULL, 15, "");
+
+       /* GML2: Polygon */
+       do_gml2_extent_test(
+           "POLYGON((1 7,7 14, 14 7, 1 7))",
+           "<Box><coordinates>1,7 14,14</coordinates></Box>",
+           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))))",
+           "<Box><coordinates>-15,-6 14,14</coordinates></Box>",
+           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)))",
+           "<Box><coordinates>-2,-1 10,14</coordinates></Box>",
+           NULL, 15, "");
+
+       /* GML2: empty (FIXME) */
+       do_gml2_extent_test(
+           "GEOMETRYCOLLECTION EMPTY",
+           "<Box><coordinates>0,0 0,0</coordinates></Box>",
+           NULL, 15, "");
+
+}
+
+static void out_gml3_extent(void)
+{
+       /* GML3: Point */
+       do_gml3_extent_test(
+           "POINT(-15 60)",
+           "<Envelope><lowerCorner>-15 60</lowerCorner><upperCorner>-15 60</upperCorner></Envelope>",
+           NULL, 15, 0, "");
+       do_gml3_extent_test(
+           "POINT(-15 60)",
+           "<gml:Envelope><gml:lowerCorner>-15 60</gml:lowerCorner><gml:upperCorner>-15 60</gml:upperCorner></gml:Envelope>",
+           NULL, 15, 0, "gml:");
+       do_gml3_extent_test(
+           "POINT(-15 60)",
+           "<Envelope srsName=\"urn:ogc:def:crs:EPSG::4326\"><lowerCorner>-15 60</lowerCorner><upperCorner>-15 60</upperCorner></Envelope>",
+           "urn:ogc:def:crs:EPSG::4326", 15, 0, "");
+
+       /* GML3: Multipoint */
+       do_gml3_extent_test(
+           "MULTIPOINT(2 3, -5 -6)",
+           "<Envelope><lowerCorner>-5 -6</lowerCorner><upperCorner>2 3</upperCorner></Envelope>",
+           NULL, 15, 0, "");
+
+       /* GML3: Linestring */
+       do_gml3_extent_test(
+           "LINESTRING(0 1,2 3,4 5)",
+           "<Envelope><lowerCorner>0 1</lowerCorner><upperCorner>4 5</upperCorner></Envelope>",
+           NULL, 15, 0, "");
+
+       /* GML3: MultiLinestring */
+       do_gml3_extent_test(
+           "MULTILINESTRING((0 1,2 3),(4 5, 10 6))",
+           "<Envelope><lowerCorner>0 1</lowerCorner><upperCorner>10 6</upperCorner></Envelope>",
+           NULL, 15, 0, "");
+       do_gml3_extent_test(
+           "MULTILINESTRING((0 1,2 3),(4 5, 10 6))",
+           "<Envelope><lowerCorner>1 0</lowerCorner><upperCorner>6 10</upperCorner></Envelope>",
+           NULL, 15, LW_GML_IS_DEGREE, "");
+       do_gml3_extent_test(
+           "MULTILINESTRING((0 1,2 3),(4 5, 10 6))",
+           "<Envelope srsDimension=\"2\"><lowerCorner>1 0</lowerCorner><upperCorner>6 10</upperCorner></Envelope>",
+           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))",
+           "<Envelope srsDimension=\"3\"><lowerCorner>1 0 -70</lowerCorner><upperCorner>6 10 50</upperCorner></Envelope>",
+           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))",
+           "<Envelope><lowerCorner>1 7</lowerCorner><upperCorner>14 14</upperCorner></Envelope>",
+           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))))",
+           "<Envelope><lowerCorner>-15 -6</lowerCorner><upperCorner>14 14</upperCorner></Envelope>",
+           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)))",
+           "<Envelope><lowerCorner>-2 -1</lowerCorner><upperCorner>10 14</upperCorner></Envelope>",
+           NULL, 15, 0, "");
+
+       /* GML3: empty (FIXME) */
+       do_gml3_extent_test(
+           "GEOMETRYCOLLECTION EMPTY",
+           "<Envelope><lowerCorner>0 0</lowerCorner><upperCorner>0 0</upperCorner></Envelope>",
+           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};
index ccc7d52544700ab6f4a74676308fd431af68b1ad..2b2c151997fbb7dcea6381c6ed368ce25454bb05 100644 (file)
@@ -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("<Envelope><lowerCorner><upperCorner>//") + (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, "</%slowerCorner>", 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);
+}
        
        
 /**