[postgis-commits] svn - r2707 - in trunk: doc lwgeom

postgis-commits at postgis.refractions.net postgis-commits at postgis.refractions.net
Thu Sep 6 09:03:58 PDT 2007


Author: mcayland
Date: 2007-09-06 09:03:56 -0700 (Thu, 06 Sep 2007)
New Revision: 2707

Modified:
   trunk/doc/postgis.xml
   trunk/lwgeom/lwgeom_gml.c
   trunk/lwgeom/lwpostgis.sql.in
Log:
Commit modified version of Barbara Phillipot's GML patch to fix existing output to make it GML2 compliant, plus add GML3 output capability

Modified: trunk/doc/postgis.xml
===================================================================
--- trunk/doc/postgis.xml	2007-09-05 14:26:14 UTC (rev 2706)
+++ trunk/doc/postgis.xml	2007-09-06 16:03:56 UTC (rev 2707)
@@ -4249,10 +4249,12 @@
           </varlistentry>
 
           <varlistentry>
-            <term>ST_AsGML(geometry, [precision])</term>
+            <term>ST_AsGML([version], geometry, [precision])</term>
 
             <listitem>
-              <para>Return the geometry as a GML element. Second argument may
+              <para>Return the geometry as a GML element. The version parameter,
+              if specified, may be either 2 or 3. If no version parameter is
+	      specified then the default is assumed to be 2. The third argument may
               be used to reduce the maximum number of significant digits used
               in output (defaults to 15).</para>
             </listitem>

Modified: trunk/lwgeom/lwgeom_gml.c
===================================================================
--- trunk/lwgeom/lwgeom_gml.c	2007-09-05 14:26:14 UTC (rev 2706)
+++ trunk/lwgeom/lwgeom_gml.c	2007-09-06 16:03:56 UTC (rev 2707)
@@ -22,21 +22,34 @@
 #include "liblwgeom.h"
 
 Datum LWGEOM_asGML(PG_FUNCTION_ARGS);
-char *geometry_to_gml(uchar *srl, char *srs);
 
-static size_t asgml_point_size(LWPOINT *point, char *srs);
-static char *asgml_point(LWPOINT *point, char *srs);
-static size_t asgml_line_size(LWLINE *line, char *srs);
-static char *asgml_line(LWLINE *line, char *srs);
-static size_t asgml_poly_size(LWPOLY *poly, char *srs);
-static char *asgml_poly(LWPOLY *poly, char *srs);
-static size_t asgml_inspected_size(LWGEOM_INSPECTED *geom, char *srs);
-static char *asgml_inspected(LWGEOM_INSPECTED *geom, char *srs);
+char *geometry_to_gml2(uchar *srl, char *srs);
+
+static size_t asgml2_point_size(LWPOINT *point, char *srs);
+static char *asgml2_point(LWPOINT *point, char *srs);
+static size_t asgml2_line_size(LWLINE *line, char *srs);
+static char *asgml2_line(LWLINE *line, char *srs);
+static size_t asgml2_poly_size(LWPOLY *poly, char *srs);
+static char *asgml2_poly(LWPOLY *poly, char *srs);
+static size_t asgml2_inspected_size(LWGEOM_INSPECTED *geom, char *srs);
+static char *asgml2_inspected(LWGEOM_INSPECTED *geom, char *srs);
+static size_t pointArray_toGML2(POINTARRAY *pa, char *buf);
+
+char *geometry_to_gml3(uchar *srl, char *srs);
+
+static size_t asgml3_point_size(LWPOINT *point, char *srs);
+static char *asgml3_point(LWPOINT *point, char *srs);
+static size_t asgml3_line_size(LWLINE *line, char *srs);
+static char *asgml3_line(LWLINE *line, char *srs);
+static size_t asgml3_poly_size(LWPOLY *poly, char *srs);
+static char *asgml3_poly(LWPOLY *poly, char *srs);
+static size_t asgml3_inspected_size(LWGEOM_INSPECTED *geom, char *srs);
+static char *asgml3_inspected(LWGEOM_INSPECTED *geom, char *srs);
+static size_t pointArray_toGML3(POINTARRAY *pa, char *buf);
+
 static size_t pointArray_GMLsize(POINTARRAY *pa);
-static size_t pointArray_toGML(POINTARRAY *pa, char *buf);
 static char *getSRSbySRID(int SRID);
 
-#define DEF_PRECISION 15
 /* Add dot, sign, exponent sign, 'e', exponent digits */
 #define SHOW_DIGS (precision + 8)
 
@@ -54,44 +67,42 @@
 	char *gml;
 	text *result;
 	int len;
-	int version = 2;
+	int version;
 	char *srs;
 	int SRID;
 
-	precision = DEF_PRECISION;
 
-	if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
+    /* Get the version */
+    version = PG_GETARG_INT32(0);
+	if ( version != 2 && version != 3 )
+	{
+		elog(ERROR, "Only GML 2 and GML 3 are supported");
+		PG_RETURN_NULL();
+	}
 
-	geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+    /* Get the geometry */
+	if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
+	geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
 
-	/* Get precision (if provided)  */
-	if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
-			precision = PG_GETARG_INT32(1);
-	
+	/* Get precision  */
+	precision = PG_GETARG_INT32(2);
 	if ( precision < 1 || precision > 15 )
 	{
 		elog(ERROR, "Precision out of range 1..15");
 		PG_RETURN_NULL();
 	}
-
-	/* Get version (if provided)  */
-	if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
-			version = PG_GETARG_INT32(2);
-
 	
-	if ( version != 2 )
-	{
-		elog(ERROR, "Only GML 2 is supported");
-		PG_RETURN_NULL();
-	}
-
 	SRID = lwgeom_getsrid(SERIALIZED_FORM(geom));
 	if ( SRID != -1 ) srs = getSRSbySRID(SRID);
 	else srs = NULL;
 
 	/*elog(NOTICE, "srs=%s", srs); */
 
-	gml = geometry_to_gml(SERIALIZED_FORM(geom), srs);
+	if (version == 2)
+	  gml = geometry_to_gml2(SERIALIZED_FORM(geom), srs);
+	else
+	  gml = geometry_to_gml3(SERIALIZED_FORM(geom), srs);
+	
 	PG_FREE_IF_COPY(geom, 0);
 
 	len = strlen(gml) + VARHDRSZ;
@@ -106,9 +117,15 @@
 	PG_RETURN_POINTER(result);
 }
 
+
+
+/*
+ * VERSION GML 2 
+ */
+
 /* takes a GEOMETRY and returns a GML representation */
 char *
-geometry_to_gml(uchar *geom, char *srs)
+geometry_to_gml2(uchar *geom, char *srs)
 {
 	int type;
 	LWPOINT *point;
@@ -123,24 +140,24 @@
 
 		case POINTTYPE:
 			point = lwpoint_deserialize(geom);
-			return asgml_point(point, srs);
+			return asgml2_point(point, srs);
 
 		case LINETYPE:
 			line = lwline_deserialize(geom);
-			return asgml_line(line, srs);
+			return asgml2_line(line, srs);
 
 		case POLYGONTYPE:
 			poly = lwpoly_deserialize(geom);
-			return asgml_poly(poly, srs);
+			return asgml2_poly(poly, srs);
 
 		default:
 			inspected = lwgeom_inspect(geom);
-			return asgml_inspected(inspected, srs);
+			return asgml2_inspected(inspected, srs);
 	}
 }
 
 static size_t
-asgml_point_size(LWPOINT *point, char *srs)
+asgml2_point_size(LWPOINT *point, char *srs)
 {
 	int size;
 	size = pointArray_GMLsize(point->point);
@@ -150,7 +167,7 @@
 }
 
 static size_t
-asgml_point_buf(LWPOINT *point, char *srs, char *output)
+asgml2_point_buf(LWPOINT *point, char *srs, char *output)
 {
 	char *ptr = output;
 
@@ -160,26 +177,26 @@
 		ptr += sprintf(ptr, "<gml:Point>");
 	}
 	ptr += sprintf(ptr, "<gml:coordinates>");
-	ptr += pointArray_toGML(point->point, ptr);
+	ptr += pointArray_toGML2(point->point, ptr);
 	ptr += sprintf(ptr, "</gml:coordinates></gml:Point>");
 
 	return (ptr-output);
 }
 
 static char *
-asgml_point(LWPOINT *point, char *srs)
+asgml2_point(LWPOINT *point, char *srs)
 {
 	char *output;
 	int size;
 	
-	size = asgml_point_size(point, srs);
+	size = asgml2_point_size(point, srs);
 	output = palloc(size);
-	asgml_point_buf(point, srs, output);
+	asgml2_point_buf(point, srs, output);
 	return output;
 }
 
 static size_t
-asgml_line_size(LWLINE *line, char *srs)
+asgml2_line_size(LWLINE *line, char *srs)
 {
 	int size;
 	size = pointArray_GMLsize(line->points);
@@ -189,7 +206,7 @@
 }
 
 static size_t
-asgml_line_buf(LWLINE *line, char *srs, char *output)
+asgml2_line_buf(LWLINE *line, char *srs, char *output)
 {
 	char *ptr=output;
 
@@ -199,33 +216,33 @@
 		ptr += sprintf(ptr, "<gml:LineString>");
 	}
 	ptr += sprintf(ptr, "<gml:coordinates>");
-	ptr += pointArray_toGML(line->points, ptr);
+	ptr += pointArray_toGML2(line->points, ptr);
 	ptr += sprintf(ptr, "</gml:coordinates></gml:LineString>");
 
 	return (ptr-output);
 }
 
 static char *
-asgml_line(LWLINE *line, char *srs)
+asgml2_line(LWLINE *line, char *srs)
 {
 	char *output;
 	int size;
 
-	size = asgml_line_size(line, srs);
+	size = asgml2_line_size(line, srs);
 	output = palloc(size);
-	asgml_line_buf(line, srs, output);
+	asgml2_line_buf(line, srs, output);
 	return output;
 }
 
 static size_t
-asgml_poly_size(LWPOLY *poly, char *srs)
+asgml2_poly_size(LWPOLY *poly, char *srs)
 {
 	size_t size;
 	int i;
 
 	size = sizeof("<gml:polygon></gml:polygon>");
-	size += sizeof("<gml:outerboundaryis><gml:linearring>/") * 2;
-	size += sizeof("<gml:innerboundaryis><gml:linearring>/") * 2 *
+	size += sizeof("<gml:outerboundaryis><gml:linearring><gml:coordinates>/") * 2;
+	size += sizeof("<gml:innerboundaryis><gml:linearring><gml:coordinates>/") * 2 *
 		poly->nrings;
 	if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
 
@@ -236,7 +253,7 @@
 }
 
 static size_t
-asgml_poly_buf(LWPOLY *poly, char *srs, char *output)
+asgml2_poly_buf(LWPOLY *poly, char *srs, char *output)
 {
 	int i;
 	char *ptr=output;
@@ -246,14 +263,14 @@
 	} else {
  		ptr += sprintf(ptr, "<gml:Polygon>");
 	}
- 	ptr += sprintf(ptr, "<gml:OuterBoundaryIs>");
-	ptr += pointArray_toGML(poly->rings[0], ptr);
- 	ptr += sprintf(ptr, "</gml:OuterBoundaryIs>");
+ 	ptr += sprintf(ptr, "<gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>");
+	ptr += pointArray_toGML2(poly->rings[0], ptr);
+ 	ptr += sprintf(ptr, "</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs>");
 	for (i=1; i<poly->nrings; i++)
 	{
- 		ptr += sprintf(ptr, "<gml:InnerBoundaryIs>");
-		ptr += pointArray_toGML(poly->rings[i], ptr);
- 		ptr += sprintf(ptr, "</gml:InnerBoundaryIs>");
+ 		ptr += sprintf(ptr, "<gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>");
+		ptr += pointArray_toGML2(poly->rings[i], ptr);
+ 		ptr += sprintf(ptr, "</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs>");
 	}
 	ptr += sprintf(ptr, "</gml:Polygon>");
 
@@ -261,14 +278,14 @@
 }
 
 static char *
-asgml_poly(LWPOLY *poly, char *srs)
+asgml2_poly(LWPOLY *poly, char *srs)
 {
 	char *output;
 	int size;
 
-	size = asgml_poly_size(poly, srs);
+	size = asgml2_poly_size(poly, srs);
 	output = palloc(size);
-	asgml_poly_buf(poly, srs, output);
+	asgml2_poly_buf(poly, srs, output);
 	return output;
 }
 
@@ -278,7 +295,7 @@
  * Don't call this with single-geoms inspected.
  */
 static size_t
-asgml_inspected_size(LWGEOM_INSPECTED *insp, char *srs)
+asgml2_inspected_size(LWGEOM_INSPECTED *insp, char *srs)
 {
 	int i;
 	size_t size;
@@ -297,24 +314,24 @@
 
 		if ((point=lwgeom_getpoint_inspected(insp, i)))
 		{
-			size += asgml_point_size(point, 0);
+			size += asgml2_point_size(point, 0);
 			pfree_point(point);
 		}
 		else if ((line=lwgeom_getline_inspected(insp, i)))
 		{
-			size += asgml_line_size(line, 0);
+			size += asgml2_line_size(line, 0);
 			pfree_line(line);
 		}
 		else if ((poly=lwgeom_getpoly_inspected(insp, i)))
 		{
-			size += asgml_poly_size(poly, 0);
+			size += asgml2_poly_size(poly, 0);
 			pfree_polygon(poly);
 		}
 		else
 		{
 			subgeom = lwgeom_getsubgeometry_inspected(insp, i);
 			subinsp = lwgeom_inspect(subgeom);
-			size += asgml_inspected_size(subinsp, 0);
+			size += asgml2_inspected_size(subinsp, 0);
 			pfree_inspected(subinsp);
 		}
 	}
@@ -326,7 +343,7 @@
  * Don't call this with single-geoms inspected!
  */
 static size_t
-asgml_inspected_buf(LWGEOM_INSPECTED *insp, char *srs, char *output)
+asgml2_inspected_buf(LWGEOM_INSPECTED *insp, char *srs, char *output)
 {
 	int type = lwgeom_getType(insp->serialized_form[0]);
 	char *ptr, *gmltype;
@@ -356,24 +373,30 @@
 
 		if ((point=lwgeom_getpoint_inspected(insp, i)))
 		{
-			ptr += asgml_point_buf(point, 0, ptr);
+		  ptr += sprintf(ptr, "<gml:pointMember>");
+			ptr += asgml2_point_buf(point, 0, ptr);
 			pfree_point(point);
+			ptr += sprintf(ptr, "</gml:pointMember>");
 		}
 		else if ((line=lwgeom_getline_inspected(insp, i)))
 		{
-			ptr += asgml_line_buf(line, 0, ptr);
+		  ptr += sprintf(ptr, "<gml:lineStringMember>");
+			ptr += asgml2_line_buf(line, 0, ptr);
 			pfree_line(line);
+			ptr += sprintf(ptr, "</gml:lineStringMember>");
 		}
 		else if ((poly=lwgeom_getpoly_inspected(insp, i)))
 		{
-			ptr += asgml_poly_buf(poly, 0, ptr);
+		  ptr += sprintf(ptr, "<gml:polygonMember>");
+			ptr += asgml2_poly_buf(poly, 0, ptr);
 			pfree_polygon(poly);
+			ptr += sprintf(ptr, "</gml:polygonMember>");
 		}
 		else
 		{
 			subgeom = lwgeom_getsubgeometry_inspected(insp, i);
 			subinsp = lwgeom_inspect(subgeom);
-			ptr += asgml_inspected_buf(subinsp, 0, ptr);
+			ptr += asgml2_inspected_buf(subinsp, 0, ptr);
 			pfree_inspected(subinsp);
 		}
 	}
@@ -388,30 +411,376 @@
  * Don't call this with single-geoms inspected!
  */
 static char *
-asgml_inspected(LWGEOM_INSPECTED *insp, char *srs)
+asgml2_inspected(LWGEOM_INSPECTED *insp, char *srs)
 {
 	char *gml;
 	size_t size;
 
-	size = asgml_inspected_size(insp, srs);
+	size = asgml2_inspected_size(insp, srs);
 	gml = palloc(size);
-	asgml_inspected_buf(insp, srs, gml);
+	asgml2_inspected_buf(insp, srs, gml);
 	return gml;
 }
 
+static size_t
+pointArray_toGML2(POINTARRAY *pa, char *output)
+{
+	int i;
+	char *ptr;
+
+	ptr = output;
+
+	if ( ! TYPE_HASZ(pa->dims) )
+	{
+		for (i=0; i<pa->npoints; i++)
+		{
+			POINT2D pt;
+			getPoint2d_p(pa, i, &pt);
+			if ( i ) ptr += sprintf(ptr, " ");
+			ptr += sprintf(ptr, "%.*g,%.*g",
+				precision, pt.x,
+				precision, pt.y);
+		}
+	}
+	else 
+	{
+		for (i=0; i<pa->npoints; i++)
+		{
+			POINT4D pt;
+			getPoint4d_p(pa, i, &pt);
+			if ( i ) ptr += sprintf(ptr, " ");
+			ptr += sprintf(ptr, "%.*g,%.*g,%.*g",
+				precision, pt.x,
+				precision, pt.y,
+				precision, pt.z);
+		}
+	}
+
+	return ptr-output;
+}
+
+
 /*
- * Returns maximum size of rendered pointarray in bytes.
+ * VERSION GML 3.1.1 
  */
+
+
+/* takes a GEOMETRY and returns a GML representation */
+char *
+geometry_to_gml3(uchar *geom, char *srs)
+{
+	int type;
+	LWPOINT *point;
+	LWLINE *line;
+	LWPOLY *poly;
+	LWGEOM_INSPECTED *inspected;
+
+	type = lwgeom_getType(geom[0]);
+
+	switch (type)
+	{
+
+		case POINTTYPE:
+			point = lwpoint_deserialize(geom);
+			return asgml3_point(point, srs);
+
+		case LINETYPE:
+			line = lwline_deserialize(geom);
+			return asgml3_line(line, srs);
+
+		case POLYGONTYPE:
+			poly = lwpoly_deserialize(geom);
+			return asgml3_poly(poly, srs);
+
+		default:
+			inspected = lwgeom_inspect(geom);
+			return asgml3_inspected(inspected, srs);
+
+	}
+}
+
 static size_t
-pointArray_GMLsize(POINTARRAY *pa)
+asgml3_point_size(LWPOINT *point, char *srs)
 {
-	return TYPE_NDIMS(pa->dims) * pa->npoints * (SHOW_DIGS+(TYPE_NDIMS(pa->dims)-1));
+	int size;
+	size = pointArray_GMLsize(point->point);
+	size += sizeof("<gml:point><gml:pos>/") * 2;
+	if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
+	return size;
 }
 
 static size_t
-pointArray_toGML(POINTARRAY *pa, char *output)
+asgml3_point_buf(LWPOINT *point, char *srs, char *output)
 {
+	char *ptr = output;
+
+	if ( srs ) {
+		ptr += sprintf(ptr, "<gml:Point srsName=\"%s\">", srs);
+	} else {
+		ptr += sprintf(ptr, "<gml:Point>");
+	}
+	ptr += sprintf(ptr, "<gml:pos>");
+	ptr += pointArray_toGML3(point->point, ptr);
+	ptr += sprintf(ptr, "</gml:pos></gml:Point>");
+
+	return (ptr-output);
+}
+
+static char *
+asgml3_point(LWPOINT *point, char *srs)
+{
+	char *output;
+	int size;
+	
+	size = asgml3_point_size(point, srs);
+	output = palloc(size);
+	asgml3_point_buf(point, srs, output);
+	return output;
+}
+
+
+static size_t
+asgml3_line_size(LWLINE *line, char *srs)
+{
+	int size;
+	size = pointArray_GMLsize(line->points);
+	size += sizeof("<gml:Curve><gml:segments><gml:LineStringSegment><gml:posList>/") * 2;
+	if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
+	return size;
+}
+
+static size_t
+asgml3_line_buf(LWLINE *line, char *srs, char *output)
+{
+	char *ptr=output;
+
+	if ( srs ) {
+		ptr += sprintf(ptr, "<gml:Curve srsName=\"%s\">", srs);
+	} else {
+		ptr += sprintf(ptr, "<gml:Curve>");
+	}
+	ptr += sprintf(ptr, "<gml:segments>");
+	ptr += sprintf(ptr, "<gml:LineStringSegment>");
+	ptr += sprintf(ptr, "<gml:posList>");
+	ptr += pointArray_toGML3(line->points, ptr);
+	ptr += sprintf(ptr, "</gml:posList></gml:LineStringSegment>");
+	ptr += sprintf(ptr, "</gml:segments>");
+	ptr += sprintf(ptr, "</gml:Curve>");
+
+	return (ptr-output);
+}
+
+static char *
+asgml3_line(LWLINE *line, char *srs)
+{
+	char *output;
+	int size;
+
+	size = asgml3_line_size(line, srs);
+	output = palloc(size);
+	asgml3_line_buf(line, srs, output);
+	return output;
+}
+
+
+static size_t
+asgml3_poly_size(LWPOLY *poly, char *srs)
+{
+	size_t size;
 	int i;
+
+	size = sizeof("<gml:Polygon>");
+
+	size += sizeof("<gml:exterior><gml:LinearRing><gml:posList>");
+	size += sizeof("</gml:posList></gml:LinearRing></gml:exterior>");
+
+	size += sizeof("<gml:interior><gml:LinearRing><gml:posList>") * (poly->nrings - 1);
+	size += sizeof("</gml:posList></gml:LinearRing></gml:interior>") * (poly->nrings - 1);
+
+	size += sizeof("</gml:Polygon>");
+
+	if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
+
+	for (i=0; i<poly->nrings; i++)
+		size += pointArray_GMLsize(poly->rings[i]);
+
+	return size;
+}
+
+static size_t
+asgml3_poly_buf(LWPOLY *poly, char *srs, char *output)
+{
+	int i;
+	char *ptr=output;
+
+	if ( srs ) {
+ 		ptr += sprintf(ptr, "<gml:Polygon srsName=\"%s\">", srs);
+	} else {
+ 		ptr += sprintf(ptr, "<gml:Polygon>");
+	}
+ 	ptr += sprintf(ptr, "<gml:exterior><gml:LinearRing><gml:posList>");
+	ptr += pointArray_toGML3(poly->rings[0], ptr);
+ 	ptr += sprintf(ptr, "</gml:posList></gml:LinearRing></gml:exterior>");
+	for (i=1; i<poly->nrings; i++)
+	{
+ 		ptr += sprintf(ptr, "<gml:interior><gml:LinearRing><gml:posList>");
+		ptr += pointArray_toGML3(poly->rings[i], ptr);
+ 		ptr += sprintf(ptr, "</gml:posList></gml:LinearRing></gml:interior>");
+	}
+	ptr += sprintf(ptr, "</gml:Polygon>");
+
+	return (ptr-output);
+}
+
+static char *
+asgml3_poly(LWPOLY *poly, char *srs)
+{
+	char *output;
+	int size;
+
+	size = asgml3_poly_size(poly, srs);
+	output = palloc(size);
+	asgml3_poly_buf(poly, srs, output);
+	return output;
+}
+/*
+ * Compute max size required for GML version of this 
+ * inspected geometry. Will recurse when needed.
+ * Don't call this with single-geoms inspected.
+ */
+static size_t
+asgml3_inspected_size(LWGEOM_INSPECTED *insp, char *srs)
+{
+	int i;
+	size_t size;
+
+	/* the longest possible multi version */
+	size = sizeof("<gml:MultiLineString></gml:MultiLineString>");
+	if ( srs ) size += strlen(srs) + sizeof(" srsName=..");
+
+	for (i=0; i<insp->ngeometries; i++)
+	{
+		LWPOINT *point;
+		LWLINE *line;
+		LWPOLY *poly;
+		LWGEOM_INSPECTED *subinsp;
+		uchar *subgeom;
+
+		if ((point=lwgeom_getpoint_inspected(insp, i)))
+		{
+			size += asgml3_point_size(point, 0);
+			pfree_point(point);
+		}
+		else if ((line=lwgeom_getline_inspected(insp, i)))
+		{
+			size += asgml3_line_size(line, 0);
+			pfree_line(line);
+		}
+		else if ((poly=lwgeom_getpoly_inspected(insp, i)))
+		{
+			size += asgml3_poly_size(poly, 0);
+			pfree_polygon(poly);
+		}
+		else
+		{
+			subgeom = lwgeom_getsubgeometry_inspected(insp, i);
+			subinsp = lwgeom_inspect(subgeom);
+			size += asgml3_inspected_size(subinsp, 0);
+			pfree_inspected(subinsp);
+		}
+	}
+
+	return size;
+}
+
+/*
+ * Don't call this with single-geoms inspected!
+ */
+static size_t
+asgml3_inspected_buf(LWGEOM_INSPECTED *insp, char *srs, char *output)
+{
+	int type = lwgeom_getType(insp->serialized_form[0]);
+	char *ptr, *gmltype;
+	int i;
+
+	ptr = output;
+
+	if (type == MULTIPOINTTYPE) gmltype = "MultiPoint";
+	else if (type == MULTILINETYPE) gmltype = "MultiCurve";
+	else if (type == MULTIPOLYGONTYPE) gmltype = "MultiSurface";
+	else gmltype = "MultiGeometry";
+
+	/* Open outmost tag */
+	if ( srs ) {
+		ptr += sprintf(ptr, "<gml:%s srsName=\"%s\">", gmltype, srs);
+	} else {
+		ptr += sprintf(ptr, "<gml:%s>", gmltype);
+	}
+
+	for (i=0; i<insp->ngeometries; i++)
+	{
+		LWPOINT *point;
+		LWLINE *line;
+		LWPOLY *poly;
+		LWGEOM_INSPECTED *subinsp;
+		uchar *subgeom;
+
+		if ((point=lwgeom_getpoint_inspected(insp, i)))
+		{
+		  ptr += sprintf(ptr, "<gml:pointMember>");
+			ptr += asgml3_point_buf(point, 0, ptr);
+			pfree_point(point);
+			ptr += sprintf(ptr, "</gml:pointMember>");
+		}
+		else if ((line=lwgeom_getline_inspected(insp, i)))
+		{
+		  ptr += sprintf(ptr, "<gml:curveMember>");
+			ptr += asgml3_line_buf(line, 0, ptr);
+			pfree_line(line);
+			ptr += sprintf(ptr, "</gml:curveMember>");
+		}
+		else if ((poly=lwgeom_getpoly_inspected(insp, i)))
+		{
+		  ptr += sprintf(ptr, "<gml:surfaceMember>");
+			ptr += asgml3_poly_buf(poly, 0, ptr);
+			pfree_polygon(poly);
+			ptr += sprintf(ptr, "</gml:surfaceMember>");
+		}
+		else
+		{
+			subgeom = lwgeom_getsubgeometry_inspected(insp, i);
+			subinsp = lwgeom_inspect(subgeom);
+			ptr += asgml3_inspected_buf(subinsp, 0, ptr);
+			pfree_inspected(subinsp);
+		}
+	}
+
+	/* Close outmost tag */
+	ptr += sprintf(ptr, "</gml:%s>", gmltype);
+
+	return (ptr-output);
+}
+
+/*
+ * Don't call this with single-geoms inspected!
+ */
+static char *
+asgml3_inspected(LWGEOM_INSPECTED *insp, char *srs)
+{
+	char *gml;
+	size_t size;
+
+	size = asgml3_inspected_size(insp, srs);
+	gml = palloc(size);
+	asgml3_inspected_buf(insp, srs, gml);
+	return gml;
+}
+
+/* In GML3, inside <posList> or <pos>, coordinates are separated by a space separator*/
+static size_t
+pointArray_toGML3(POINTARRAY *pa, char *output)
+{
+	int i;
 	char *ptr;
 
 	ptr = output;
@@ -423,7 +792,7 @@
 			POINT2D pt;
 			getPoint2d_p(pa, i, &pt);
 			if ( i ) ptr += sprintf(ptr, " ");
-			ptr += sprintf(ptr, "%.*g,%.*g",
+			ptr += sprintf(ptr, "%.*g %.*g",
 				precision, pt.x,
 				precision, pt.y);
 		}
@@ -435,7 +804,7 @@
 			POINT4D pt;
 			getPoint4d_p(pa, i, &pt);
 			if ( i ) ptr += sprintf(ptr, " ");
-			ptr += sprintf(ptr, "%.*g,%.*g,%.*g",
+			ptr += sprintf(ptr, "%.*g %.*g,%.*g",
 				precision, pt.x,
 				precision, pt.y,
 				precision, pt.z);
@@ -445,6 +814,12 @@
 	return ptr-output;
 }
 
+
+
+/*
+ * Common GML routines 
+ */
+
 static char *
 getSRSbySRID(int SRID)
 {
@@ -503,6 +878,16 @@
 	return srscopy;
 }
 
+/*
+ * Returns maximum size of rendered pointarray in bytes.
+ */
+static size_t
+pointArray_GMLsize(POINTARRAY *pa)
+{
+	return TYPE_NDIMS(pa->dims) * pa->npoints * (SHOW_DIGS+(TYPE_NDIMS(pa->dims)-1));
+}
+
+
 /**********************************************************************
  * $Log$
  * Revision 1.13  2006/01/09 15:55:55  strk

Modified: trunk/lwgeom/lwpostgis.sql.in
===================================================================
--- trunk/lwgeom/lwpostgis.sql.in	2007-09-05 14:26:14 UTC (rev 2706)
+++ trunk/lwgeom/lwpostgis.sql.in	2007-09-06 16:03:56 UTC (rev 2707)
@@ -4673,45 +4673,52 @@
 -----------------------------------------------------------------------
 -- GML OUTPUT
 -----------------------------------------------------------------------
--- AsGML(geom, precision, version)
--- Deprecation in 1.2.3
-CREATEFUNCTION AsGML(geometry, int4, int4)
+-- _ST_AsGML(version, geom, precision)
+CREATEFUNCTION _ST_AsGML(int4, geometry, int4)
 	RETURNS TEXT
 	AS '@MODULE_FILENAME@','LWGEOM_asGML'
 	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
--- Availability: 1.2.2
-CREATEFUNCTION ST_AsGML(geometry, int4, int4)
-	RETURNS TEXT
-	AS '@MODULE_FILENAME@','LWGEOM_asGML'
-	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
-
 -- AsGML(geom, precision) / version=2
 -- Deprecation in 1.2.3
 CREATEFUNCTION AsGML(geometry, int4)
 	RETURNS TEXT
-	AS '@MODULE_FILENAME@','LWGEOM_asGML'
-	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+	AS 'SELECT _ST_AsGML(2, $1, $2)'
+	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
 -- Availability: 1.2.2
 CREATEFUNCTION ST_AsGML(geometry, int4)
 	RETURNS TEXT
-	AS '@MODULE_FILENAME@','LWGEOM_asGML'
-	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+	AS 'SELECT _ST_AsGML(2, $1, $2)'
+	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
 -- AsGML(geom) / precision=15 version=2
 -- Deprecation in 1.2.3
 CREATEFUNCTION AsGML(geometry)
 	RETURNS TEXT
-	AS '@MODULE_FILENAME@','LWGEOM_asGML'
-	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+	AS 'SELECT _ST_AsGML(2, $1, 15)'
+	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
 -- Availabiltiy: 1.2.2
 CREATEFUNCTION ST_AsGML(geometry)
 	RETURNS TEXT
-	AS '@MODULE_FILENAME@','LWGEOM_asGML'
-	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+	AS 'SELECT _ST_AsGML(2, $1, 15)'
+	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
+-- ST_AsGML(version, geom) / precision=15 version=2
+-- Availabiltiy: 1.3.2
+CREATEFUNCTION ST_AsGML(int4, geometry)
+	RETURNS TEXT
+	AS 'SELECT _ST_AsGML($1, $2, 15)'
+	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+
+-- ST_AsGML(version, geom, precision)
+-- Availabiltiy: 1.3.2
+CREATEFUNCTION ST_AsGML(int4, geometry, int4)
+	RETURNS TEXT
+	AS 'SELECT _ST_AsGML($1, $2, $3)'
+	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+
 -----------------------------------------------------------------------
 -- KML OUTPUT
 -----------------------------------------------------------------------



More information about the postgis-commits mailing list