From: Paul Ramsey Date: Wed, 5 Feb 2014 17:43:48 +0000 (+0000) Subject: #2632, ST_AsGML for curve types X-Git-Tag: 2.2.0rc1~1255 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=58014e647f7e16e41b6552c1ddef8deaf65c7a75;p=postgis #2632, ST_AsGML for curve types git-svn-id: http://svn.osgeo.org/postgis/trunk@12227 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index 751da565c..e97a1244c 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,7 @@ PostGIS 2.2.0 - #2430, ST_ForceCurve - #2565, ST_SummaryStatsAgg() - #2567, ST_CountAgg() + - #2632, ST_AsGML() support for curved features * Enhancements * diff --git a/liblwgeom/cunit/cu_out_gml.c b/liblwgeom/cunit/cu_out_gml.c index 80c9f5765..76e0d19cd 100644 --- a/liblwgeom/cunit/cu_out_gml.c +++ b/liblwgeom/cunit/cu_out_gml.c @@ -550,25 +550,26 @@ static void out_gml_test_geoms(void) "0 12 3 4 5", NULL, 0, 0); - - /* GML2 - CircularString */ do_gml2_unsupported( "CIRCULARSTRING(-2 0,0 2,2 0,0 2,2 4)", "lwgeom_to_gml2: 'CircularString' geometry type not supported"); /* GML3 - CircularString */ - do_gml3_unsupported( - "CIRCULARSTRING(-2 0,0 2,2 0,0 2,2 4)", - "lwgeom_to_gml3: 'CircularString' geometry type not supported"); + do_gml3_test( + "CIRCULARSTRING(-2 0,0 2,2 0,0 2,2 4)", + "-2 0 0 2 2 0 0 2 2 4", + NULL, 0, 0 ); /* GML2 - CompoundCurve */ do_gml2_unsupported( "COMPOUNDCURVE(CIRCULARSTRING(0 0,1 1,1 0),(1 0,0 1))", "lwgeom_to_gml2: 'CompoundCurve' geometry type not supported"); /* GML3 - CompoundCurve */ - do_gml3_unsupported( - "COMPOUNDCURVE(CIRCULARSTRING(0 0,1 1,1 0),(1 0,0 1))", - "lwgeom_to_gml3: 'CompoundCurve' geometry type not supported"); + + do_gml3_test( + "COMPOUNDCURVE(CIRCULARSTRING(0 0,1 1,1 0),(1 0,0 1))", + "0 0 1 1 1 01 0 0 1", + NULL, 0, 0 ); /* GML2 - CurvePolygon */ do_gml2_unsupported( @@ -576,9 +577,10 @@ static void out_gml_test_geoms(void) "lwgeom_to_gml2: 'CurvePolygon' geometry type not supported"); /* GML3 - CurvePolygon */ - do_gml3_unsupported( - "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))", - "lwgeom_to_gml3: 'CurvePolygon' geometry type not supported"); + do_gml3_test( + "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))", + "-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", + NULL, 1, 0 ); /* GML2 - MultiCurve */ @@ -587,9 +589,10 @@ static void out_gml_test_geoms(void) "lwgeom_to_gml2: 'MultiCurve' geometry type not supported"); /* GML3 - MultiCurve */ - do_gml3_unsupported( - "MULTICURVE((5 5,3 5,3 3,0 3),CIRCULARSTRING(0 0,2 1,2 2))", - "lwgeom_to_gml3: 'MultiCurve' geometry type not supported"); + do_gml3_test( + "MULTICURVE((5 5,3 5,3 3,0 3),CIRCULARSTRING(0 0,2 1,2 2))", + "5 5 3 5 3 3 0 30 0 2 1 2 2", + NULL, 0, 0 ); /* GML2 - MultiSurface */ do_gml2_unsupported( @@ -597,9 +600,10 @@ static void out_gml_test_geoms(void) "lwgeom_to_gml2: 'MultiSurface' geometry type not supported"); /* GML3 - MultiSurface */ - do_gml3_unsupported( - "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)))", - "lwgeom_to_gml3: 'MultiSurface' geometry type not supported"); + do_gml3_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 0 -1 -1 0 0 1 -1 2 0 0 2 -2 0-1 0 0 0.5 1 0 0 1 -1 07 8 10 10 6 14 4 11 7 8", + NULL, 1, 0 ); /* GML2 - PolyhedralSurface */ do_gml2_unsupported( diff --git a/liblwgeom/lwout_gml.c b/liblwgeom/lwout_gml.c index 8d108a18f..47366b68a 100644 --- a/liblwgeom/lwout_gml.c +++ b/liblwgeom/lwout_gml.c @@ -39,8 +39,10 @@ static size_t asgml3_point_size(const LWPOINT *point, const char *srs, int preci static char *asgml3_point(const LWPOINT *point, const char *srs, int precision, int opts, const char *prefix, const char *id); static size_t asgml3_line_size(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id); static char *asgml3_line(const LWLINE *line, const char *srs, int precision, int opts, const char *prefix, const char *id); +static char *asgml3_circstring( const LWCIRCSTRING *circ, const char *srs, int precision, int opts, const char *prefix, const char *id ); static size_t asgml3_poly_size(const LWPOLY *poly, const char *srs, int precision, int opts, const char *prefix, const char *id); static char *asgml3_poly(const LWPOLY *poly, const char *srs, int precision, int opts, int is_patch, const char *prefix, const char *id); +static char * asgml3_curvepoly(const LWCURVEPOLY* poly, const char *srs, int precision, int opts, const char *prefix, const char *id); static size_t asgml3_triangle_size(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id); static char *asgml3_triangle(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id); static size_t asgml3_multi_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id); @@ -49,20 +51,25 @@ static char *asgml3_psurface(const LWPSURFACE *psur, const char *srs, int precis static char *asgml3_tin(const LWTIN *tin, const char *srs, int precision, int opts, const char *prefix, const char *id); static size_t asgml3_collection_size(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id); static char *asgml3_collection(const LWCOLLECTION *col, const char *srs, int precision, int opts, const char *prefix, const char *id); +static char *asgml3_compound(const LWCOMPOUND *col, const char *srs, int precision, int opts, const char *prefix, const char *id ); +static char *asgml3_multicurve( const LWMCURVE* cur, const char *srs, int precision, int opts, const char *prefix, const char *id ); +static char *asgml3_multisurface(const LWMSURFACE *sur, const char *srs, int precision, int opts, const char *prefix, const char *id); static size_t pointArray_toGML3(POINTARRAY *pa, char *buf, int precision, int opts); + static size_t pointArray_GMLsize(POINTARRAY *pa, int precision); static char * gbox_to_gml2(const GBOX *bbox, const char *srs, int precision, const char *prefix) { int size; - POINT4D pt; - POINTARRAY *pa; + POINT4D pt; + POINTARRAY *pa; char *ptr, *output; size_t prefixlen = strlen(prefix); - if ( ! bbox ) { + if ( ! bbox ) + { size = ( sizeof("/") + (prefixlen*2) ) * 2; if ( srs ) size += strlen(srs) + sizeof(" srsName=.."); @@ -77,17 +84,17 @@ gbox_to_gml2(const GBOX *bbox, const char *srs, int precision, const char *prefi return output; } - pa = ptarray_construct_empty(FLAGS_GET_Z(bbox->flags), 0, 2); + pa = ptarray_construct_empty(FLAGS_GET_Z(bbox->flags), 0, 2); + + 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 = 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 = bbox->xmax; - pt.y = bbox->ymax; - if (FLAGS_GET_Z(bbox->flags)) pt.z = bbox->zmax; - ptarray_append_point(pa, &pt, LW_TRUE); + 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); size += ( sizeof("/") + (prefixlen*2) ) * 2; @@ -102,7 +109,7 @@ gbox_to_gml2(const GBOX *bbox, const char *srs, int precision, const char *prefi ptr += pointArray_toGML2(pa, ptr, precision); ptr += sprintf(ptr, "", prefix, prefix); - ptarray_free(pa); + ptarray_free(pa); return output; } @@ -111,13 +118,14 @@ static char * gbox_to_gml3(const GBOX *bbox, const char *srs, int precision, int opts, const char *prefix) { int size; - POINT4D pt; - POINTARRAY *pa; + POINT4D pt; + POINTARRAY *pa; char *ptr, *output; size_t prefixlen = strlen(prefix); int dimension = 2; - if ( ! bbox ) { + if ( ! bbox ) + { size = ( sizeof("/") + (prefixlen*2) ) * 2; if ( srs ) size += strlen(srs) + sizeof(" srsName=.."); @@ -131,14 +139,14 @@ gbox_to_gml3(const GBOX *bbox, const char *srs, int precision, int opts, const c return output; } - if (FLAGS_GET_Z(bbox->flags)) dimension = 3; + if (FLAGS_GET_Z(bbox->flags)) dimension = 3; - pa = ptarray_construct_empty(FLAGS_GET_Z(bbox->flags), 0, 1); + pa = ptarray_construct_empty(FLAGS_GET_Z(bbox->flags), 0, 1); - 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 = 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; @@ -156,11 +164,11 @@ gbox_to_gml3(const GBOX *bbox, const char *srs, int precision, int opts, const c ptr += pointArray_toGML3(pa, ptr, precision, opts); ptr += sprintf(ptr, "", prefix); - ptarray_remove_point(pa, 0); - 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); + ptarray_remove_point(pa, 0); + 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); ptr += pointArray_toGML3(pa, ptr, precision, opts); @@ -168,7 +176,7 @@ gbox_to_gml3(const GBOX *bbox, const char *srs, int precision, int opts, const c ptr += sprintf(ptr, "", prefix); - ptarray_free(pa); + ptarray_free(pa); return output; } @@ -178,31 +186,31 @@ 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; - } -*/ + /* + 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; - } -*/ + /* + 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); } - - + + /** * @brief VERSION GML 2 * takes a GEOMETRY and returns a GML2 representation @@ -240,7 +248,7 @@ lwgeom_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char* p case TINTYPE: lwerror("Cannot convert %s to GML2. Try ST_AsGML(3, ) to generate GML3.", lwtype_name(type)); return NULL; - + default: lwerror("lwgeom_to_gml2: '%s' geometry type not supported", lwtype_name(type)); return NULL; @@ -266,7 +274,8 @@ asgml2_point_buf(const LWPOINT *point, const char *srs, char *output, int precis ptr += sprintf(ptr, "<%sPoint", prefix); if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); - if ( lwpoint_is_empty(point) ) { + if ( lwpoint_is_empty(point) ) + { ptr += sprintf(ptr, "/>"); return (ptr-output); } @@ -311,7 +320,8 @@ asgml2_line_buf(const LWLINE *line, const char *srs, char *output, int precision ptr += sprintf(ptr, "<%sLineString", prefix); if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); - if ( lwline_is_empty(line) ) { + if ( lwline_is_empty(line) ) + { ptr += sprintf(ptr, "/>"); return (ptr-output); } @@ -345,7 +355,7 @@ asgml2_poly_size(const LWPOLY *poly, const char *srs, int precision, const char size = sizeof("") + prefixlen*2; if ( srs ) size += strlen(srs) + sizeof(" srsName=.."); - if ( lwpoly_is_empty(poly) ) + if ( lwpoly_is_empty(poly) ) return size; size += ( sizeof("/") + ( prefixlen*3) ) * 2; size += ( sizeof("/") + ( prefixlen*2) ) * 2 * poly->nrings; @@ -365,13 +375,14 @@ asgml2_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision ptr += sprintf(ptr, "<%sPolygon", prefix); if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); - if ( lwpoly_is_empty(poly) ) { + if ( lwpoly_is_empty(poly) ) + { ptr += sprintf(ptr, "/>"); return (ptr-output); } ptr += sprintf(ptr, ">"); ptr += sprintf(ptr, "<%souterBoundaryIs><%sLinearRing><%scoordinates>", - prefix, prefix, prefix); + prefix, prefix, prefix); ptr += pointArray_toGML2(poly->rings[0], ptr, precision); ptr += sprintf(ptr, "", prefix, prefix, prefix); for (i=1; inrings; i++) @@ -463,7 +474,8 @@ asgml2_multi_buf(const LWCOLLECTION *col, const char *srs, char *output, ptr += sprintf(ptr, "<%s%s", prefix, gmltype); if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); - if (!col->ngeoms) { + if (!col->ngeoms) + { ptr += sprintf(ptr, "/>"); return (ptr-output); } @@ -535,7 +547,7 @@ asgml2_collection_size(const LWCOLLECTION *col, const char *srs, int precision, for (i=0; ingeoms; i++) { subgeom = col->geoms[i]; - + size += ( sizeof("/") + prefixlen ) * 2; if ( subgeom->type == POINTTYPE) { @@ -570,14 +582,15 @@ asgml2_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, in char *ptr; int i; LWGEOM *subgeom; - + ptr = output; /* Open outmost tag */ ptr += sprintf(ptr, "<%sMultiGeometry", prefix); if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); - if (!col->ngeoms) { + if (!col->ngeoms) + { ptr += sprintf(ptr, "/>"); return (ptr-output); } @@ -585,7 +598,7 @@ asgml2_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, in for (i=0; ingeoms; i++) { - subgeom = col->geoms[i]; + subgeom = col->geoms[i]; ptr += sprintf(ptr, "<%sgeometryMember>", prefix); if (subgeom->type == POINTTYPE) @@ -724,9 +737,15 @@ lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, con case LINETYPE: return asgml3_line((LWLINE*)geom, srs, precision, opts, prefix, id); + case CIRCSTRINGTYPE: + return asgml3_circstring((LWCIRCSTRING*)geom, srs, precision, opts, prefix, id ); + case POLYGONTYPE: return asgml3_poly((LWPOLY*)geom, srs, precision, opts, 0, prefix, id); + case CURVEPOLYTYPE: + return asgml3_curvepoly((LWCURVEPOLY*)geom, srs, precision, opts, prefix, id); + case TRIANGLETYPE: return asgml3_triangle((LWTRIANGLE*)geom, srs, precision, opts, prefix, id); @@ -744,6 +763,15 @@ lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, con case COLLECTIONTYPE: return asgml3_collection((LWCOLLECTION*)geom, srs, precision, opts, prefix, id); + case COMPOUNDTYPE: + return asgml3_compound( (LWCOMPOUND*)geom, srs, precision, opts, prefix, id ); + + case MULTICURVETYPE: + return asgml3_multicurve( (LWMCURVE*)geom, srs, precision, opts, prefix, id ); + + case MULTISURFACETYPE: + return asgml3_multisurface( (LWMSURFACE*)geom, srs, precision, opts, prefix, id ); + default: lwerror("lwgeom_to_gml3: '%s' geometry type not supported", lwtype_name(type)); return NULL; @@ -775,7 +803,8 @@ asgml3_point_buf(const LWPOINT *point, const char *srs, char *output, int precis ptr += sprintf(ptr, "<%sPoint", prefix); if ( srs ) ptr += sprintf(ptr, " srsName=\"%s\"", srs); if ( id ) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id); - if ( lwpoint_is_empty(point) ) { + if ( lwpoint_is_empty(point) ) + { ptr += sprintf(ptr, "/>"); return (ptr-output); } @@ -812,16 +841,16 @@ asgml3_line_size(const LWLINE *line, const char *srs, int precision, int opts, c if ( opts & LW_GML_SHORTLINE ) { size += ( - sizeof("/") + - ( prefixlen * 2 ) - ) * 2; + sizeof("/") + + ( prefixlen * 2 ) + ) * 2; } else { size += ( - sizeof("/") + - ( prefixlen * 4 ) - ) * 2; + sizeof("/") + + ( prefixlen * 4 ) + ) * 2; } if (srs) size += strlen(srs) + sizeof(" srsName=.."); if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=.."); @@ -838,30 +867,38 @@ asgml3_line_buf(const LWLINE *line, const char *srs, char *output, int precision if (FLAGS_GET_Z(line->flags)) dimension = 3; - if ( shortline ) { + if ( shortline ) + { ptr += sprintf(ptr, "<%sLineString", prefix); - } else { + } + else + { ptr += sprintf(ptr, "<%sCurve", prefix); } if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs); if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id); - if ( lwline_is_empty(line) ) { + if ( lwline_is_empty(line) ) + { ptr += sprintf(ptr, "/>"); return (ptr-output); } ptr += sprintf(ptr, ">"); - if ( ! shortline ) { + if ( ! shortline ) + { ptr += sprintf(ptr, "<%ssegments>", prefix); ptr += sprintf(ptr, "<%sLineStringSegment>", prefix); } - if (IS_DIMS(opts)) { + if (IS_DIMS(opts)) + { ptr += sprintf(ptr, "<%sposList srsDimension=\"%d\">", - prefix, dimension); - } else { + prefix, dimension); + } + else + { ptr += sprintf(ptr, "<%sposList>", prefix); } @@ -869,9 +906,12 @@ asgml3_line_buf(const LWLINE *line, const char *srs, char *output, int precision ptr += sprintf(ptr, "", prefix); - if ( shortline ) { + if ( shortline ) + { ptr += sprintf(ptr, "", prefix); - } else { + } + else + { ptr += sprintf(ptr, "", prefix); ptr += sprintf(ptr, "", prefix); ptr += sprintf(ptr, "", prefix); @@ -893,6 +933,71 @@ asgml3_line(const LWLINE *line, const char *srs, int precision, int opts, const } +static size_t +asgml3_circstring_size(const LWCIRCSTRING *circ, const char *srs, int precision, int opts, const char *prefix, const char *id) +{ + int size = pointArray_GMLsize( circ->points, precision ); + size_t prefixlen = strlen(prefix); + size += 2 * ( sizeof( "/" ) + 2 * prefixlen ); + size += 2 * ( sizeof( "/" ) + 2 * prefixlen ); + if (srs) size += strlen(srs) + sizeof(" srsName=.."); + if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=.."); + if (IS_DIMS(opts)) size += sizeof(" srsDimension='x'"); + return size; +} + +static size_t +asgml3_circstring_buf(const LWCIRCSTRING *circ, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id) +{ + char* ptr = output; + int dimension=2; + + if (FLAGS_GET_Z(circ->flags)) + { + dimension = 3; + } + + ptr += sprintf(ptr, "<%sCurve", prefix); + if (srs) + { + ptr += sprintf(ptr, " srsName=\"%s\"", srs); + } + if (id) + { + ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id); + } + ptr += sprintf(ptr, ">"); + ptr += sprintf(ptr, "<%ssegments>", prefix); + ptr += sprintf(ptr, "<%sArcString>", prefix); + ptr += sprintf(ptr, "<%sposList", prefix); + + if (IS_DIMS(opts)) + { + ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension); + } + ptr += sprintf(ptr, ">"); + + ptr += pointArray_toGML3(circ->points, ptr, precision, opts); + ptr += sprintf(ptr, "", prefix); + ptr += sprintf(ptr, "", prefix); + ptr += sprintf(ptr, "", prefix); + ptr += sprintf(ptr, "", prefix); + return (ptr-output); +} + +static char * +asgml3_circstring( const LWCIRCSTRING *circ, const char *srs, int precision, int opts, const char *prefix, const char *id ) +{ + char *output; + int size; + + size = asgml3_circstring_size(circ, srs, precision, opts, prefix, id); + output = lwalloc( size ); + asgml3_circstring_buf(circ, srs, output, precision, opts, prefix, id); + return output; +} + + static size_t asgml3_poly_size(const LWPOLY *poly, const char *srs, int precision, int opts, const char *prefix, const char *id) { @@ -934,7 +1039,8 @@ asgml3_poly_buf(const LWPOLY *poly, const char *srs, char *output, int precision if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs); if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id); - if ( lwpoly_is_empty(poly) ) { + if ( lwpoly_is_empty(poly) ) + { ptr += sprintf(ptr, "/>"); return (ptr-output); } @@ -974,6 +1080,126 @@ asgml3_poly(const LWPOLY *poly, const char *srs, int precision, int opts, int is return output; } +static size_t asgml3_curvepoly_size(const LWCURVEPOLY* poly, const char *srs, int precision, int opts, const char *prefix, const char *id) +{ + size_t prefixlen = strlen(prefix); + LWGEOM* subgeom; + size_t size = sizeof( "nrings; ++i ) + { + if( i == 0 ) + { + size += sizeof( "" ) + 2 * prefixlen; + } + else + { + size += sizeof( "" ) + 2 * prefixlen; + } + subgeom = poly->rings[i]; + + if ( subgeom->type == LINETYPE ) + { + size += sizeof("") + 2 * prefixlen; + size += sizeof("points, precision ); + } + else if( subgeom->type == CIRCSTRINGTYPE ) + { + size += sizeof("") + 2 * prefixlen; + size += asgml3_circstring_size((LWCIRCSTRING*)subgeom, srs, precision, opts, prefix, id); + } + } + return size; +} + +static size_t asgml3_curvepoly_buf(const LWCURVEPOLY* poly, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id) +{ + int i; + LWGEOM* subgeom; + char *ptr=output; + int dimension=2; + + if (FLAGS_GET_Z(poly->flags)) + { + dimension = 3; + } + + ptr += sprintf( ptr, "<%sPolygon", prefix ); + if (srs) + { + ptr += sprintf(ptr, " srsName=\"%s\"", srs); + } + if (id) + { + ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id ); + } + ptr += sprintf(ptr, ">"); + + for( i = 0; i < poly->nrings; ++i ) + { + if( i == 0 ) + { + ptr += sprintf( ptr, "<%sexterior>", prefix); + } + else + { + ptr += sprintf( ptr, "<%sinterior>", prefix); + } + + subgeom = poly->rings[i]; + if ( subgeom->type == LINETYPE ) + { + ptr += sprintf( ptr, "<%sLinearRing>", prefix ); + ptr += sprintf( ptr, "<%sposList", prefix ); + if (IS_DIMS(opts)) + { + ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension); + } + ptr += sprintf( ptr, ">" ); + ptr += pointArray_toGML3(((LWLINE*)subgeom)->points, ptr, precision, opts); + ptr += sprintf( ptr, "", prefix ); + ptr += sprintf( ptr, "", prefix ); + } + else if( subgeom->type == CIRCSTRINGTYPE ) + { + ptr += sprintf( ptr, "<%scurveMember>", prefix ); + ptr += asgml3_circstring_buf( (LWCIRCSTRING*)subgeom, srs, ptr, precision, opts, prefix, id ); + ptr += sprintf( ptr, "", prefix ); + } + + if( i == 0 ) + { + ptr += sprintf( ptr, "", prefix); + } + else + { + ptr += sprintf( ptr, "", prefix); + } + } + + ptr += sprintf( ptr, "", prefix ); + return (ptr - output); +} + +static char* asgml3_curvepoly(const LWCURVEPOLY* poly, const char *srs, int precision, int opts, const char *prefix, const char *id) +{ + char* gml; + size_t size; + + size = asgml3_curvepoly_size( poly, srs, precision, opts, prefix, id ); + gml = lwalloc( size ); + asgml3_curvepoly_buf( poly, srs, gml, precision, opts, prefix, id ); + return gml; +} + static size_t asgml3_triangle_size(const LWTRIANGLE *triangle, const char *srs, int precision, int opts, const char *prefix, const char *id) @@ -1095,7 +1321,8 @@ asgml3_multi_buf(const LWCOLLECTION *col, const char *srs, char *output, int pre if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs); if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id); - if (!col->ngeoms) { + if (!col->ngeoms) + { ptr += sprintf(ptr, "/>"); return (ptr-output); } @@ -1329,7 +1556,8 @@ asgml3_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, in if (srs) ptr += sprintf(ptr, " srsName=\"%s\"", srs); if (id) ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id); - if (!col->ngeoms) { + if (!col->ngeoms) + { ptr += sprintf(ptr, "/>"); return (ptr-output); } @@ -1358,9 +1586,9 @@ asgml3_collection_buf(const LWCOLLECTION *col, const char *srs, char *output, in else ptr += asgml3_multi_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, prefix, id); } - else + else lwerror("asgml3_collection_buf: unknown geometry type"); - + ptr += sprintf(ptr, "", prefix); } @@ -1385,6 +1613,262 @@ asgml3_collection(const LWCOLLECTION *col, const char *srs, int precision, int o return gml; } +static size_t asgml3_compound_size(const LWCOMPOUND *col, const char *srs, int precision, int opts, const char *prefix, const char *id ) +{ + int i; + size_t size; + LWGEOM *subgeom; + size_t prefixlen = strlen(prefix); + + size = ( sizeof( "" ) + 2 * prefixlen ); + + if (srs) size += strlen(srs) + sizeof(" srsName=.."); + if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=.."); + + size += ( sizeof("") + 2 * prefixlen ); + + for(i= 0; i < col->ngeoms; ++i ) + { + subgeom = col->geoms[i]; + if ( subgeom->type == LINETYPE ) + { + + size += sizeof( "points, precision ); + } + else if( subgeom->type == CIRCSTRINGTYPE ) + { + size += sizeof( "") + 4 * prefixlen; + size += pointArray_GMLsize( ((LWCIRCSTRING*)subgeom)->points, precision ); + } + else + { + continue; + } + if (IS_DIMS(opts)) + { + size += sizeof(" srsDimension='x'"); + } + } + return size; +} + +static size_t asgml3_compound_buf(const LWCOMPOUND *col, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id) +{ + LWGEOM *subgeom; + int i; + char* ptr = output; + int dimension=2; + + if (FLAGS_GET_Z(col->flags)) + { + dimension = 3; + } + + ptr += sprintf( ptr, "<%sCurve", prefix ); + if (srs) + { + ptr += sprintf(ptr, " srsName=\"%s\"", srs); + } + if (id) + { + ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id ); + } + ptr += sprintf( ptr, ">" ); + ptr += sprintf( ptr, "<%ssegments>", prefix ); + + for( i = 0; i < col->ngeoms; ++i ) + { + subgeom = col->geoms[i]; + if( subgeom->type != LINETYPE && subgeom->type != CIRCSTRINGTYPE ) + { + continue; + } + + if ( subgeom->type == LINETYPE ) + { + ptr += sprintf( ptr, "<%sLineStringSegment><%sposList", prefix, prefix ); + if (IS_DIMS(opts)) + { + ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension); + } + ptr += sprintf(ptr, ">"); + ptr += pointArray_toGML3(((LWCIRCSTRING*)subgeom)->points, ptr, precision, opts); + ptr += sprintf( ptr, "", prefix, prefix ); + } + else if( subgeom->type == CIRCSTRINGTYPE ) + { + ptr += sprintf( ptr, "<%sArcString><%sposList" , prefix, prefix ); + if (IS_DIMS(opts)) + { + ptr += sprintf(ptr, " srsDimension=\"%d\"", dimension); + } + ptr += sprintf(ptr, ">"); + ptr += pointArray_toGML3(((LWLINE*)subgeom)->points, ptr, precision, opts); + ptr += sprintf( ptr, "", prefix, prefix ); + } + } + + ptr += sprintf( ptr, "", prefix ); + ptr += sprintf( ptr, "", prefix ); + return ( ptr - output ); +} + +static char *asgml3_compound(const LWCOMPOUND *col, const char *srs, int precision, int opts, const char *prefix, const char *id ) +{ + char* gml; + size_t size; + + size = asgml3_compound_size( col, srs, precision, opts, prefix, id ); + gml = lwalloc( size ); + asgml3_compound_buf( col, srs, gml, precision, opts, prefix, id ); + return gml; +} + +static size_t asgml3_multicurve_size( const LWMCURVE* cur, const char *srs, int precision, int opts, const char *prefix, const char *id ) +{ + size_t prefixlen = strlen(prefix); + size_t size = sizeof( "" ) + 2 * prefixlen; + if (srs) size += strlen(srs) + sizeof(" srsName=.."); + if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=.."); + LWGEOM* subgeom; + int i; + + for( i = 0; i < cur->ngeoms; ++i ) + { + size += sizeof( "" ) + 2 * prefixlen; + subgeom = cur->geoms[i]; + if ( subgeom->type == LINETYPE ) + { + size += asgml3_line_size( (LWLINE*)subgeom, srs, precision, opts, prefix, id ); + } + else if( subgeom->type == CIRCSTRINGTYPE ) + { + size += asgml3_circstring_size( (LWCIRCSTRING*)subgeom, srs, precision, opts, prefix, id ); + } + else if( subgeom->type == COMPOUNDTYPE ) + { + size += asgml3_compound_size( (LWCOMPOUND*)subgeom, srs, precision, opts, prefix, id ); + } + } + return size; +} + +static size_t asgml3_multicurve_buf( const LWMCURVE* cur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id ) +{ + char* ptr = output; + LWGEOM* subgeom; + int i; + + ptr += sprintf(ptr, "<%sMultiCurve", prefix ); + if (srs) + { + ptr += sprintf(ptr, " srsName=\"%s\"", srs); + } + if (id) + { + ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id ); + } + ptr += sprintf( ptr, ">"); + + for( i = 0; i < cur->ngeoms; ++i ) + { + ptr += sprintf(ptr, "<%scurveMember>", prefix ); + subgeom = cur->geoms[i]; + if ( subgeom->type == LINETYPE ) + { + ptr += asgml3_line_buf( (LWLINE*)subgeom, srs, ptr, precision, opts, prefix, id ); + } + else if( subgeom->type == CIRCSTRINGTYPE ) + { + ptr += asgml3_circstring_buf( (LWCIRCSTRING*)subgeom, srs, ptr, precision, opts, prefix, id ); + } + else if( subgeom->type == COMPOUNDTYPE ) + { + ptr += asgml3_compound_buf( (LWCOMPOUND*)subgeom, srs, ptr, precision, opts, prefix, id ); + } + ptr += sprintf(ptr, "", prefix ); + } + ptr += sprintf(ptr, "", prefix ); + return (ptr - output); +} + +static char *asgml3_multicurve( const LWMCURVE* cur, const char *srs, int precision, int opts, const char *prefix, const char *id ) +{ + char* gml; + size_t size =asgml3_multicurve_size( cur, srs, precision, opts, prefix, id ); + gml = lwalloc( size ); + asgml3_multicurve_buf( cur, srs, gml, precision, opts, prefix, id ); + return gml; +} + +static size_t asgml3_multisurface_size(const LWMSURFACE *sur, const char *srs, int precision, int opts, const char *prefix, const char *id) +{ + size_t prefixlen = strlen(prefix); + size_t size = sizeof( "" ) + 2 * prefixlen; + if (srs) size += strlen(srs) + sizeof(" srsName=.."); + if (id) size += strlen(id) + strlen(prefix) + sizeof(" id=.."); + LWGEOM* subgeom; + int i; + + for( i = 0; i < sur->ngeoms; ++i ) + { + subgeom = sur->geoms[i]; + if( subgeom->type == POLYGONTYPE ) + { + size += asgml3_poly_size( (LWPOLY*)sur->geoms[i], srs, precision, opts, prefix, id ); + } + else if( subgeom->type == CURVEPOLYTYPE ) + { + size += asgml3_curvepoly_size( (LWCURVEPOLY*)sur->geoms[i], srs, precision, opts, prefix, id ); + } + } + return size; +} + +static size_t asgml3_multisurface_buf(const LWMSURFACE *sur, const char *srs, char *output, int precision, int opts, const char *prefix, const char *id) +{ + char* ptr = output; + int i; + LWGEOM* subgeom; + + ptr += sprintf( ptr, "<%sMultiSurface", prefix ); + if (srs) + { + ptr += sprintf(ptr, " srsName=\"%s\"", srs); + } + if (id) + { + ptr += sprintf(ptr, " %sid=\"%s\"", prefix, id ); + } + ptr += sprintf( ptr, ">" ); + + for( i = 0; i < sur->ngeoms; ++i ) + { + subgeom = sur->geoms[i]; + if( subgeom->type == POLYGONTYPE ) + { + ptr += asgml3_poly_buf( (LWPOLY*)sur->geoms[i], srs, ptr, precision, opts, 0, prefix, id ); + } + else if( subgeom->type == CURVEPOLYTYPE ) + { + ptr += asgml3_curvepoly_buf( (LWCURVEPOLY*)sur->geoms[i], srs, ptr, precision, opts, prefix, id ); + } + } + ptr += sprintf( ptr, "", prefix ); + return ptr - output; +} + +static char *asgml3_multisurface(const LWMSURFACE *sur, const char *srs, int precision, int opts, const char *prefix, const char *id) +{ + char* gml; + size_t size = asgml3_multisurface_size( sur, srs, precision, opts, prefix, id ); + gml = lwalloc( size ); + asgml3_multisurface_buf( sur, srs, gml, precision, opts, prefix, id ); + return gml; +} + /* In GML3, inside or , coordinates are separated by a space separator * In GML3 also, lat/lon are reversed for geocentric data diff --git a/regress/out_geometry.sql b/regress/out_geometry.sql index f3fa4af66..a31b56383 100644 --- a/regress/out_geometry.sql +++ b/regress/out_geometry.sql @@ -50,6 +50,13 @@ SELECT 'gml_shortline_02', ST_AsGML(3, GeomFromEWKT('LINESTRING(1 2, 3 4)'), 0, SELECT 'gml_shortline_03', ST_AsGML(3, GeomFromEWKT('MULTILINESTRING((1 2, 3 4), (5 6, 7 8))'), 0, 6, ''); SELECT 'gml_shortline_04', ST_AsGML(3, GeomFromEWKT('MULTILINESTRING((1 2, 3 4), (5 6, 7 8))'), 0, 2, ''); +-- CIRCULARSTRING / COMPOUNDCURVE / CURVEPOLYGON / MULTISURFACE / MULTICURVE +SELECT 'gml_out_curve_01', ST_AsGML( 3, GeomFromEWKT('CIRCULARSTRING(-2 0,0 2,2 0,0 2,2 4)')); +SELECT 'gml_out_curve_02', ST_ASGML( 3, GeomFromEWKT('COMPOUNDCURVE(CIRCULARSTRING(0 0,1 1,1 0),(1 0,0 1))')); +SELECT 'gml_out_curve_03', ST_AsGML( 3, GeomFromEWKT('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))')); +SELECT 'gml_out_curve_04', ST_AsGML( 3, GeomFromEWKT('MULTICURVE((5 5,3 5,3 3,0 3),CIRCULARSTRING(0 0,2 1,2 2))')); +SELECT 'gml_out_curve_05', ST_AsGML( 3, GeomFromEWKT('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)))')); + -- -- KML -- diff --git a/regress/out_geometry_expected b/regress/out_geometry_expected index 82b1a207c..c81714965 100644 --- a/regress/out_geometry_expected +++ b/regress/out_geometry_expected @@ -22,6 +22,11 @@ gml_shortline_01|1 2 3 4 gml_shortline_02|1 2 3 4 gml_shortline_03|1 2 3 45 6 7 8 gml_shortline_04|1 2 3 45 6 7 8 +gml_out_curve_01|-2 0 0 2 2 0 0 2 2 4 +gml_out_curve_02|0 0 1 1 1 01 0 0 1 +gml_out_curve_03|-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 +gml_out_curve_04|5 5 3 5 3 3 0 30 0 2 1 2 2 +gml_out_curve_05|-2 0 -1 -1 0 0 1 -1 2 0 0 2 -2 0-1 0 0 0.5 1 0 0 1 -1 07 8 10 10 6 14 4 11 7 8 ERROR: GetProj4StringSPI: Cannot find SRID (10) in spatial_ref_sys ERROR: Input geometry has unknown (0) SRID kml_empty_geom|