[postgis-commits] svn - r2748 - in trunk: . lwgeom

postgis-commits at postgis.refractions.net postgis-commits at postgis.refractions.net
Fri Mar 28 14:10:28 PDT 2008


Author: pramsey
Date: 2008-03-28 14:10:28 -0700 (Fri, 28 Mar 2008)
New Revision: 2748

Modified:
   trunk/ChangeLog
   trunk/lwgeom/lwgeom_kml.c
   trunk/lwgeom/lwpostgis.sql.in
Log:
Revert KML patch, bad puppy!


Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2008-03-28 21:04:46 UTC (rev 2747)
+++ trunk/ChangeLog	2008-03-28 21:10:28 UTC (rev 2748)
@@ -1,12 +1,5 @@
 2008-03-28 Paul Ramsey <pramsey at cleverelephant.ca>
 
-        * lwgeom/lwgeom_kml.c, lwgeom/lwpostgis.sql.in
-          Added patch from Eduin Carillo to enhance KML
-          support. 
-          http://code.google.com/p/postgis/issues/detail?id=17
-
-2008-03-28 Paul Ramsey <pramsey at cleverelephant.ca>
-
         * doc/postgis.xml, lwgeom/lwgeom_svn.c,
           Added patch from Marco Hugentobler to enhance SVG 
           support. 2008-February/002883.html

Modified: trunk/lwgeom/lwgeom_kml.c
===================================================================
--- trunk/lwgeom/lwgeom_kml.c	2008-03-28 21:04:46 UTC (rev 2747)
+++ trunk/lwgeom/lwgeom_kml.c	2008-03-28 21:10:28 UTC (rev 2748)
@@ -1,5 +1,5 @@
 /**********************************************************************
- * $Id: $
+ * $Id$
  *
  * PostGIS - Spatial Types for PostgreSQL
  * http://postgis.refractions.net
@@ -10,7 +10,7 @@
  *
  **********************************************************************
  *
- * KML output routines based on lwgeom_gml.c
+ * KML output routines based on  lwgeom_gml.c
  * Written by: Eduin Carrillo <yecarrillo at cas.gov.co>
  *             © 2006 Corporacion Autonoma Regional de Santander - CAS
  *
@@ -24,21 +24,21 @@
 #include "liblwgeom.h"
 
 Datum LWGEOM_asKML(PG_FUNCTION_ARGS);
+char *geometry_to_kml(uchar *srl, char *srs);
 
-char *geometry_to_kml2(uchar *srl);
-
-static size_t askml2_point_size(LWPOINT *point);
-static char *askml2_point(LWPOINT *point);
-static size_t askml2_line_size(LWLINE *line);
-static char *askml2_line(LWLINE *line);
-static size_t askml2_poly_size(LWPOLY *poly);
-static char *askml2_poly(LWPOLY *poly);
-static size_t askml2_inspected_size(LWGEOM_INSPECTED *geom);
-static char *askml2_inspected(LWGEOM_INSPECTED *geom);
-static size_t pointArray_toKML2(POINTARRAY *pa, char *buf);
-
+static size_t askml_point_size(LWPOINT *point, char *srs);
+static char *askml_point(LWPOINT *point, char *srs);
+static size_t askml_line_size(LWLINE *line, char *srs);
+static char *askml_line(LWLINE *line, char *srs);
+static size_t askml_poly_size(LWPOLY *poly, char *srs);
+static char *askml_poly(LWPOLY *poly, char *srs);
+static size_t askml_inspected_size(LWGEOM_INSPECTED *geom, char *srs);
+static char *askml_inspected(LWGEOM_INSPECTED *geom, char *srs);
 static size_t pointArray_KMLsize(POINTARRAY *pa);
+static size_t pointArray_toKML(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)
 
@@ -56,34 +56,51 @@
 	char *kml;
 	text *result;
 	int len;
-	int version;
+	int version = 2;
+	char *srs;
+	int SRID;
 
+	precision = DEF_PRECISION;
 
-    /* Get the version */
-    version = PG_GETARG_INT32(0);
-	if ( version != 2)
+	if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
+
+	geom = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
+
+	/* Get precision (if provided)  */
+	if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
+			precision = PG_GETARG_INT32(1);
+	
+	if ( precision < 1 || precision > 15 )
 	{
-		elog(ERROR, "Only KML 2 is supported");
+		elog(ERROR, "Precision out of range 1..15");
 		PG_RETURN_NULL();
 	}
 
-    /* Get the geometry */
-	if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
-	geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+	/* Get version (if provided)  */
+	if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
+			version = PG_GETARG_INT32(2);
 
-	/* Get precision  */
-	precision = PG_GETARG_INT32(2);
-	if ( precision < 1 || precision > 15 )
+	
+	if ( version != 2 )
 	{
-		elog(ERROR, "Precision out of range 1..15");
+		elog(ERROR, "Only KML 2 is supported");
 		PG_RETURN_NULL();
 	}
-	
-	if (version == 2)
-	  kml = geometry_to_kml2(SERIALIZED_FORM(geom));
-	
-	PG_FREE_IF_COPY(geom, 1);
 
+	SRID = lwgeom_getsrid(SERIALIZED_FORM(geom));
+	if ( SRID != -1 ) {
+	  srs = getSRSbySRID(SRID);
+	} else {
+		PG_FREE_IF_COPY(geom, 0);
+		elog(ERROR,"Input geometry has unknown (-1) SRID");
+		PG_RETURN_NULL();
+	}
+
+	/*elog(NOTICE, "srs=%s", srs); */
+
+	kml = geometry_to_kml(SERIALIZED_FORM(geom), srs);
+	PG_FREE_IF_COPY(geom, 0);
+
 	len = strlen(kml) + VARHDRSZ;
 
 	result = palloc(len);
@@ -96,15 +113,9 @@
 	PG_RETURN_POINTER(result);
 }
 
-
-
-/*
- * VERSION KML 2 
- */
-
 /* takes a GEOMETRY and returns a KML representation */
 char *
-geometry_to_kml2(uchar *geom)
+geometry_to_kml(uchar *geom, char *srs)
 {
 	int type;
 	LWPOINT *point;
@@ -119,21 +130,21 @@
 
 		case POINTTYPE:
 			point = lwpoint_deserialize(geom);
-			return askml2_point(point);
+			return askml_point(point, srs);
 
 		case LINETYPE:
 			line = lwline_deserialize(geom);
-			return askml2_line(line);
+			return askml_line(line, srs);
 
 		case POLYGONTYPE:
 			poly = lwpoly_deserialize(geom);
-			return askml2_poly(poly);
+			return askml_poly(poly, srs);
 
 		case MULTIPOINTTYPE:
 		case MULTILINETYPE:
 		case MULTIPOLYGONTYPE:
 			inspected = lwgeom_inspect(geom);
-			return askml2_inspected(inspected);
+			return askml_inspected(inspected, srs);
 		
 		default:
 			lwerror("geometry_to_kml: '%s' geometry type not supported by Google Earth", lwgeom_typename(type));
@@ -142,7 +153,7 @@
 }
 
 static size_t
-askml2_point_size(LWPOINT *point)
+askml_point_size(LWPOINT *point, char *srs)
 {
 	int size;
 	size = pointArray_KMLsize(point->point);
@@ -151,32 +162,32 @@
 }
 
 static size_t
-askml2_point_buf(LWPOINT *point, char *output)
+askml_point_buf(LWPOINT *point, char *srs, char *output)
 {
 	char *ptr = output;
 
 	ptr += sprintf(ptr, "<Point>");
 	ptr += sprintf(ptr, "<coordinates>");
-	ptr += pointArray_toKML2(point->point, ptr);
+	ptr += pointArray_toKML(point->point, ptr);
 	ptr += sprintf(ptr, "</coordinates></Point>");
 
 	return (ptr-output);
 }
 
 static char *
-askml2_point(LWPOINT *point)
+askml_point(LWPOINT *point, char *srs)
 {
 	char *output;
 	int size;
 	
-	size = askml2_point_size(point);
+	size = askml_point_size(point, srs);
 	output = palloc(size);
-	askml2_point_buf(point, output);
+	askml_point_buf(point, srs, output);
 	return output;
 }
 
 static size_t
-askml2_line_size(LWLINE *line)
+askml_line_size(LWLINE *line, char *srs)
 {
 	int size;
 	size = pointArray_KMLsize(line->points);
@@ -185,32 +196,32 @@
 }
 
 static size_t
-askml2_line_buf(LWLINE *line, char *output)
+askml_line_buf(LWLINE *line, char *srs, char *output)
 {
 	char *ptr=output;
 
 	ptr += sprintf(ptr, "<LineString>");
 	ptr += sprintf(ptr, "<coordinates>");
-	ptr += pointArray_toKML2(line->points, ptr);
+	ptr += pointArray_toKML(line->points, ptr);
 	ptr += sprintf(ptr, "</coordinates></LineString>");
 
 	return (ptr-output);
 }
 
 static char *
-askml2_line(LWLINE *line)
+askml_line(LWLINE *line, char *srs)
 {
 	char *output;
 	int size;
 
-	size = askml2_line_size(line);
+	size = askml_line_size(line, srs);
 	output = palloc(size);
-	askml2_line_buf(line, output);
+	askml_line_buf(line, srs, output);
 	return output;
 }
 
 static size_t
-askml2_poly_size(LWPOLY *poly)
+askml_poly_size(LWPOLY *poly, char *srs)
 {
 	size_t size;
 	int i;
@@ -227,19 +238,19 @@
 }
 
 static size_t
-askml2_poly_buf(LWPOLY *poly, char *output)
+askml_poly_buf(LWPOLY *poly, char *srs, char *output)
 {
 	int i;
 	char *ptr=output;
 
 	ptr += sprintf(ptr, "<Polygon>");
 	ptr += sprintf(ptr, "<outerBoundaryIs><LinearRing><coordinates>");
-	ptr += pointArray_toKML2(poly->rings[0], ptr);
+	ptr += pointArray_toKML(poly->rings[0], ptr);
 	ptr += sprintf(ptr, "</coordinates></LinearRing></outerBoundaryIs>");
 	for (i=1; i<poly->nrings; i++)
 	{
 		ptr += sprintf(ptr, "<innerBoundaryIs><LinearRing><coordinates>");
-		ptr += pointArray_toKML2(poly->rings[i], ptr);
+		ptr += pointArray_toKML(poly->rings[i], ptr);
 		ptr += sprintf(ptr, "</coordinates></LinearRing></innerBoundaryIs>");
 	}
 	ptr += sprintf(ptr, "</Polygon>");
@@ -248,14 +259,14 @@
 }
 
 static char *
-askml2_poly(LWPOLY *poly)
+askml_poly(LWPOLY *poly, char *srs)
 {
 	char *output;
 	int size;
 
-	size = askml2_poly_size(poly);
+	size = askml_poly_size(poly, srs);
 	output = palloc(size);
-	askml2_poly_buf(poly, output);
+	askml_poly_buf(poly, srs, output);
 	return output;
 }
 
@@ -265,7 +276,7 @@
  * Don't call this with single-geoms inspected.
  */
 static size_t
-askml2_inspected_size(LWGEOM_INSPECTED *insp)
+askml_inspected_size(LWGEOM_INSPECTED *insp, char *srs)
 {
 	int i;
 	size_t size;
@@ -283,24 +294,24 @@
 
 		if ((point=lwgeom_getpoint_inspected(insp, i)))
 		{
-			size += askml2_point_size(point, 0);
+			size += askml_point_size(point, 0);
 			pfree_point(point);
 		}
 		else if ((line=lwgeom_getline_inspected(insp, i)))
 		{
-			size += askml2_line_size(line, 0);
+			size += askml_line_size(line, 0);
 			pfree_line(line);
 		}
 		else if ((poly=lwgeom_getpoly_inspected(insp, i)))
 		{
-			size += askml2_poly_size(poly, 0);
+			size += askml_poly_size(poly, 0);
 			pfree_polygon(poly);
 		}
 		else
 		{
 			subgeom = lwgeom_getsubgeometry_inspected(insp, i);
 			subinsp = lwgeom_inspect(subgeom);
-			size += askml2_inspected_size(subinsp, 0);
+			size += askml_inspected_size(subinsp, 0);
 			pfree_inspected(subinsp);
 		}
 	}
@@ -312,7 +323,7 @@
  * Don't call this with single-geoms inspected!
  */
 static size_t
-askml2_inspected_buf(LWGEOM_INSPECTED *insp, char *output)
+askml_inspected_buf(LWGEOM_INSPECTED *insp, char *srs, char *output)
 {
 	char *ptr, *kmltype;
 	int i;
@@ -320,7 +331,6 @@
 	ptr = output;
 	kmltype = "MultiGeometry";
 
-	/* Open outmost tag */
 	ptr += sprintf(ptr, "<%s>", kmltype);
 
 	for (i=0; i<insp->ngeometries; i++)
@@ -333,24 +343,24 @@
 
 		if ((point=lwgeom_getpoint_inspected(insp, i)))
 		{
-			ptr += askml2_point_buf(point, 0, ptr);
+			ptr += askml_point_buf(point, 0, ptr);
 			pfree_point(point);
 		}
 		else if ((line=lwgeom_getline_inspected(insp, i)))
 		{
-			ptr += askml2_line_buf(line, 0, ptr);
+			ptr += askml_line_buf(line, 0, ptr);
 			pfree_line(line);
 		}
 		else if ((poly=lwgeom_getpoly_inspected(insp, i)))
 		{
-			ptr += askml2_poly_buf(poly, 0, ptr);
+			ptr += askml_poly_buf(poly, 0, ptr);
 			pfree_polygon(poly);
 		}
 		else
 		{
 			subgeom = lwgeom_getsubgeometry_inspected(insp, i);
 			subinsp = lwgeom_inspect(subgeom);
-			ptr += askml2_inspected_buf(subinsp, 0, ptr);
+			ptr += askml_inspected_buf(subinsp, 0, ptr);
 			pfree_inspected(subinsp);
 		}
 	}
@@ -365,20 +375,29 @@
  * Don't call this with single-geoms inspected!
  */
 static char *
-askml2_inspected(LWGEOM_INSPECTED *insp)
+askml_inspected(LWGEOM_INSPECTED *insp, char *srs)
 {
 	char *kml;
 	size_t size;
 
-	size = askml2_inspected_size(insp);
+	size = askml_inspected_size(insp, srs);
 	kml = palloc(size);
-	askml2_inspected_buf(insp, kml);
+	askml_inspected_buf(insp, srs, kml);
 	return kml;
 }
 
+/*
+ * Returns maximum size of rendered pointarray in bytes.
+ */
 static size_t
-pointArray_toKML2(POINTARRAY *pa, char *output)
+pointArray_KMLsize(POINTARRAY *pa)
 {
+	return TYPE_NDIMS(pa->dims) * pa->npoints * (SHOW_DIGS+(TYPE_NDIMS(pa->dims)-1));
+}
+
+static size_t
+pointArray_toKML(POINTARRAY *pa, char *output)
+{
 	int i;
 	char *ptr;
 
@@ -391,7 +410,7 @@
 			POINT2D pt;
 			getPoint2d_p(pa, i, &pt);
 			if ( i ) ptr += sprintf(ptr, " ");
-			ptr += sprintf(ptr, "%.*g,%.*g",
+			ptr += sprintf(ptr, "%.*g,%.*g,0",
 				precision, pt.x,
 				precision, pt.y);
 		}
@@ -413,22 +432,65 @@
 	return ptr-output;
 }
 
+static char *
+getSRSbySRID(int SRID)
+{
+	char query[128];
+	char *srs, *srscopy;
+	int size, err;
 
+	/* connect to SPI */
+	if (SPI_OK_CONNECT != SPI_connect ()) {
+		elog(NOTICE, "getSRSbySRID: could not connect to SPI manager");
+		SPI_finish();
+		return NULL;
+	}
 
-/*
- * Common KML routines 
- */
+	/* write query */
+	sprintf(query, "SELECT textcat(auth_name, textcat(':', auth_srid::text)) \
+		FROM spatial_ref_sys WHERE srid = '%d'", SRID);
+#ifdef PGIS_DEBUG
+	elog(NOTICE, "Query: %s", query);
+#endif
 
-/*
- * Returns maximum size of rendered pointarray in bytes.
- */
-static size_t
-pointArray_KMLsize(POINTARRAY *pa)
-{
-	return TYPE_NDIMS(pa->dims) * pa->npoints * (SHOW_DIGS+(TYPE_NDIMS(pa->dims)-1));
+	/* execute query */
+	err = SPI_exec(query, 1);
+	if ( err < 0 ) {
+		elog(NOTICE, "getSRSbySRID: error executing query %d", err);
+		SPI_finish();
+		return NULL;
+	}
+
+	/* no entry in spatial_ref_sys */
+	if (SPI_processed <= 0) {
+		/*elog(NOTICE, "getSRSbySRID: no record for SRID %d", SRID); */
+		SPI_finish();
+		return NULL;
+	}
+
+	/* get result  */
+	srs = SPI_getvalue(SPI_tuptable->vals[0],
+		SPI_tuptable->tupdesc, 1);
+	
+	/* NULL result */
+	if ( ! srs ) {
+		/*elog(NOTICE, "getSRSbySRID: null result"); */
+		SPI_finish();
+		return NULL;
+	}
+
+	/* copy result to upper executor context */
+	size = strlen(srs)+1;
+	srscopy = SPI_palloc(size);
+	memcpy(srscopy, srs, size);
+
+	/* disconnect from SPI */
+	SPI_finish();
+
+	return srscopy;
 }
 
 /**********************************************************************
- * $Log: $
+ * $Log$
  **********************************************************************/
 

Modified: trunk/lwgeom/lwpostgis.sql.in
===================================================================
--- trunk/lwgeom/lwpostgis.sql.in	2008-03-28 21:04:46 UTC (rev 2747)
+++ trunk/lwgeom/lwpostgis.sql.in	2008-03-28 21:10:28 UTC (rev 2748)
@@ -4801,53 +4801,83 @@
 -----------------------------------------------------------------------
 -- KML OUTPUT
 -----------------------------------------------------------------------
--- _ST_AsKML(version, geom, precision)
-CREATEFUNCTION _ST_AsKML(int4, geometry, int4)
+-- AsUKML(geom, precision, version)
+-- Deprecation in 1.2.3
+CREATEFUNCTION AsUKML(geometry, int4, int4)
 	RETURNS TEXT
 	AS '@MODULE_FILENAME@','LWGEOM_asKML'
 	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
-#ifdef USE_PROJ
--- AsKML(geom, precision) / version=2
+-- Availability: 1.2.2
+CREATEFUNCTION ST_AsUKML(geometry, int4, int4)
+	RETURNS TEXT
+	AS '@MODULE_FILENAME@','LWGEOM_asKML'
+	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+
+-- AsUKML(geom, precision) / version=2
 -- Deprecation in 1.2.3
-CREATEFUNCTION AsKML(geometry, int4)
+CREATEFUNCTION AsUKML(geometry, int4)
 	RETURNS TEXT
-	AS 'SELECT _ST_AsKML(2, transform($1,4326), $2)' 
+	AS '@MODULE_FILENAME@','LWGEOM_asKML'
+	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+
+-- Availability: 1.2.2
+CREATEFUNCTION ST_AsUKML(geometry, int4)
+	RETURNS TEXT
+	AS '@MODULE_FILENAME@','LWGEOM_asKML'
+	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+
+-- AsUKML(geom) / precision=15 version=2
+-- Deprecation in 1.2.3
+CREATEFUNCTION AsUKML(geometry)
+	RETURNS TEXT
+	AS '@MODULE_FILENAME@','LWGEOM_asKML'
+	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+
+-- Availability: 1.2.2
+CREATEFUNCTION ST_AsUKML(geometry)
+	RETURNS TEXT
+	AS '@MODULE_FILENAME@','LWGEOM_asKML'
+	LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
+
+-- AsKML(geom, precision, version)
+-- Deprecation in 1.2.3
+CREATE OR REPLACE FUNCTION AsKML(geometry, int4, int4)
+	RETURNS TEXT
+	AS 'SELECT AsUKML(transform($1,4326),$2,$3)' 
 	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
 -- Availability: 1.2.2
-CREATEFUNCTION ST_AsKML(geometry, int4)
+CREATE OR REPLACE FUNCTION ST_AsKML(geometry, int4, int4)
 	RETURNS TEXT
-	AS 'SELECT _ST_AsKML(2, transform($1,4326), $2)' 
+	AS 'SELECT AsUKML(transform($1,4326),$2,$3)' 
 	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
--- AsKML(geom) / precision=15 version=2
+-- AsKML(geom, precision) / version=2
 -- Deprecation in 1.2.3
-CREATEFUNCTION AsKML(geometry) 
+CREATE OR REPLACE FUNCTION AsKML(geometry, int4) 
 	RETURNS TEXT
-	AS 'SELECT _ST_AsKML(2, transform($1,4326), 15)' 
+	AS 'SELECT AsUKML(transform($1,4326),$2)' 
 	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
--- Availabiltiy: 1.2.2
-CREATEFUNCTION ST_AsKML(geometry)
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_AsKML(geometry, int4) 
 	RETURNS TEXT
-	AS 'SELECT _ST_AsKML(2, transform($1,4326), 15)'
+	AS 'SELECT AsUKML(transform($1,4326),$2)' 
 	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
--- ST_AsKML(version, geom) / precision=15 version=2
--- Availabiltiy: 1.3.2
-CREATEFUNCTION ST_AsKML(int4, geometry)
+-- AsKML(geom) / precision=15 version=2
+-- Deprecation in 1.2.3
+CREATE OR REPLACE FUNCTION AsKML(geometry) 
 	RETURNS TEXT
-	AS 'SELECT _ST_AsKML($1, transform($2,4326), 15)'
+	AS 'SELECT AsUKML(transform($1,4326))' 
 	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
 
--- ST_AsKML(version, geom, precision)
--- Availabiltiy: 1.3.2
-CREATEFUNCTION ST_AsKML(int4, geometry, int4) 
+-- Availability: 1.2.2
+CREATE OR REPLACE FUNCTION ST_AsKML(geometry) 
 	RETURNS TEXT
-	AS 'SELECT _ST_AsKML($1, transform($2,4326), $3)' 
+	AS 'SELECT AsUKML(transform($1,4326))' 
 	LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
-#endif
 
 ------------------------------------------------------------------------
 -- OGC defined



More information about the postgis-commits mailing list