]> granicus.if.org Git - postgis/commitdiff
Revert KML patch, bad puppy!
authorPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 28 Mar 2008 21:10:28 +0000 (21:10 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 28 Mar 2008 21:10:28 +0000 (21:10 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@2748 b70326c6-7e19-0410-871a-916f4a2858ee

ChangeLog
lwgeom/lwgeom_kml.c
lwgeom/lwpostgis.sql.in

index 7083b9613aa8492bc9ca386f9b2eac637ec76611..d6409a810e6ff6656b0fcbded2cff4e58cd19922 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,3 @@
-2008-03-28 Paul Ramsey <pramsey@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@cleverelephant.ca>
 
         * doc/postgis.xml, lwgeom/lwgeom_svn.c,
index 7a8d0d5e2b8dec5ec8fd764a035e5978bc5a998e..210f062ac3deeb624f3a1c1329bfdadc267a2761 100644 (file)
@@ -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@cas.gov.co>
  *             © 2006 Corporacion Autonoma Regional de Santander - CAS
  *
 #include "liblwgeom.h"
 
 Datum LWGEOM_asKML(PG_FUNCTION_ARGS);
-
-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);
-
+char *geometry_to_kml(uchar *srl, char *srs);
+
+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,33 +56,50 @@ Datum LWGEOM_asKML(PG_FUNCTION_ARGS)
        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)
-       {
-               elog(ERROR, "Only KML 2 is supported");
-               PG_RETURN_NULL();
-       }
+       if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
 
-    /* Get the geometry */
-       if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
-       geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+       geom = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
 
-       /* Get precision  */
-       precision = PG_GETARG_INT32(2);
+       /* Get precision (if provided)  */
+       if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
+                       precision = PG_GETARG_INT32(1);
+       
        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)
-         kml = geometry_to_kml2(SERIALIZED_FORM(geom));
-       
-       PG_FREE_IF_COPY(geom, 1);
+       if ( version != 2 )
+       {
+               elog(ERROR, "Only KML 2 is supported");
+               PG_RETURN_NULL();
+       }
+
+       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;
 
@@ -96,15 +113,9 @@ Datum LWGEOM_asKML(PG_FUNCTION_ARGS)
        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 @@ geometry_to_kml2(uchar *geom)
 
                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 @@ geometry_to_kml2(uchar *geom)
 }
 
 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 @@ askml2_point_size(LWPOINT *point)
 }
 
 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 @@ askml2_line_size(LWLINE *line)
 }
 
 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 @@ askml2_poly_size(LWPOLY *poly)
 }
 
 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 @@ askml2_poly_buf(LWPOLY *poly, char *output)
 }
 
 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 @@ askml2_poly(LWPOLY *poly)
  * 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 @@ askml2_inspected_size(LWGEOM_INSPECTED *insp)
 
                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 @@ askml2_inspected_size(LWGEOM_INSPECTED *insp)
  * 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 @@ askml2_inspected_buf(LWGEOM_INSPECTED *insp, char *output)
        ptr = output;
        kmltype = "MultiGeometry";
 
-       /* Open outmost tag */
        ptr += sprintf(ptr, "<%s>", kmltype);
 
        for (i=0; i<insp->ngeometries; i++)
@@ -333,24 +343,24 @@ askml2_inspected_buf(LWGEOM_INSPECTED *insp, char *output)
 
                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,19 +375,28 @@ askml2_inspected_buf(LWGEOM_INSPECTED *insp, char *output)
  * 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_KMLsize(POINTARRAY *pa)
+{
+       return TYPE_NDIMS(pa->dims) * pa->npoints * (SHOW_DIGS+(TYPE_NDIMS(pa->dims)-1));
+}
+
 static size_t
-pointArray_toKML2(POINTARRAY *pa, char *output)
+pointArray_toKML(POINTARRAY *pa, char *output)
 {
        int i;
        char *ptr;
@@ -391,7 +410,7 @@ pointArray_toKML2(POINTARRAY *pa, char *output)
                        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 @@ pointArray_toKML2(POINTARRAY *pa, char *output)
        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;
+       }
 
+       /* 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
+
+       /* execute query */
+       err = SPI_exec(query, 1);
+       if ( err < 0 ) {
+               elog(NOTICE, "getSRSbySRID: error executing query %d", err);
+               SPI_finish();
+               return NULL;
+       }
 
-/*
- * Common KML routines 
- */
+       /* no entry in spatial_ref_sys */
+       if (SPI_processed <= 0) {
+               /*elog(NOTICE, "getSRSbySRID: no record for SRID %d", SRID); */
+               SPI_finish();
+               return NULL;
+       }
 
-/*
- * 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));
+       /* 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$
  **********************************************************************/
 
index e7d075a36d4005deccee56b4a683d0a9edbb0a42..6aedc91bd13b47b25f0c84a8775185f8e111f2e0 100644 (file)
@@ -4801,53 +4801,83 @@ CREATEFUNCTION ST_AsGML(int4, geometry, int4)
 -----------------------------------------------------------------------
 -- 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