]> granicus.if.org Git - postgis/commitdiff
Added AsSVG().
authorSandro Santilli <strk@keybit.net>
Mon, 13 Sep 2004 13:32:01 +0000 (13:32 +0000)
committerSandro Santilli <strk@keybit.net>
Mon, 13 Sep 2004 13:32:01 +0000 (13:32 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@805 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/Makefile
lwgeom/lwgeom_svg.c [new file with mode: 0644]
lwgeom/lwpostgis.sql.in

index 8733269f22aec63562607c1f118dd30f91fe1be6..c344bfb19dd72fa42f2ccb31ff2d496be7e021b6 100644 (file)
@@ -132,7 +132,7 @@ ifeq ($(USE_STATS),1)
        override CFLAGS += -DUSE_STATS
 endif
  
-OBJS=lwgeom_pg.o lwgeom_spheroid.o lwgeom_api.o lwgeom_ogc.o lwgeom_functions_analytic.o lwgeom_geos.o lwgeom_inout.o lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o lwgeom_transform.o stringBuffer.o lwgeom_box3d.o lwgeom_box2dfloat4.o lwgeom_chip.o lex.yy.o wktparse.tab.o lwgparse.o wktunparse.o $(GEOS_WRAPPER)
+OBJS=lwgeom_pg.o lwgeom_spheroid.o lwgeom_api.o lwgeom_ogc.o lwgeom_functions_analytic.o lwgeom_geos.o lwgeom_inout.o lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o lwgeom_transform.o stringBuffer.o lwgeom_box3d.o lwgeom_box2dfloat4.o lwgeom_chip.o lex.yy.o wktparse.tab.o lwgparse.o wktunparse.o lwgeom_svg.o $(GEOS_WRAPPER)
 
 OTHERS=y.output lex.yy.c wktparse.tab.c wktparse.tab.h lwgeom.sql lwpostgis.sql
 
diff --git a/lwgeom/lwgeom_svg.c b/lwgeom/lwgeom_svg.c
new file mode 100644 (file)
index 0000000..9c300ca
--- /dev/null
@@ -0,0 +1,258 @@
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ * Copyright 2001-2003 Refractions Research Inc.
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of hte GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************
+ *
+ * SVG output routines.
+ * Originally written by: Klaus Förster <klaus@svg.cc>
+ * Patches from: Olivier Courtin <pnine@free.fr>
+ *
+ **********************************************************************/
+
+
+#include "postgres.h"
+#include "lwgeom.h"
+
+Datum assvg_geometry(PG_FUNCTION_ARGS);
+char *geometry_to_svg(LWGEOM *geometry, int svgrel, int precision);
+void print_svg_coords(char *result, POINT2D *pt, int precision);
+void print_svg_circle(char *result, POINT2D *pt, int precision);
+void print_svg_path_abs(char *result, POINTARRAY *pa, int precision);
+void print_svg_path_rel(char *result, POINTARRAY *pa, int precision);
+
+#define SHOW_DIGS_DOUBLE 15
+#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
+
+/**
+ * SVG features
+ */
+PG_FUNCTION_INFO_V1(assvg_geometry);
+Datum assvg_geometry(PG_FUNCTION_ARGS)
+{
+       LWGEOM *geom;
+       char *svg;
+       char *result;
+       int len;
+       int32 svgrel=0;
+       int32 precision=15;
+
+       if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
+
+       geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
+       // check for relative path notation
+       if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
+                       svgrel = PG_GETARG_INT32(1);
+
+       if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
+               precision = PG_GETARG_INT32(2);
+               
+       svg = geometry_to_svg(geom, svgrel, precision);
+
+       len = strlen(svg) + 5;
+
+       result= palloc(len);
+       *((int *) result) = len;
+
+       memcpy(result +4, svg, len-4);
+
+       pfree(svg);
+       PG_FREE_IF_COPY(geom, 0);
+
+       PG_RETURN_CSTRING(result);
+}
+
+
+//takes a GEOMETRY and returns a SVG representation
+char *geometry_to_svg(LWGEOM *geometry, int svgrel, int precision)
+{
+       char *result;
+       LWGEOM_INSPECTED *inspected;
+       int t,u;
+       POINT2D *pt;
+       int size;
+       int npts;
+
+       //elog(NOTICE, "precision is %d", precision);
+       size = 30;      //just enough to put in object type
+
+       if (lwgeom_getType(geometry->type) == COLLECTIONTYPE)
+       {
+               result = (char *)palloc(64); 
+               sprintf(result, "GEOMETRYCOLLECTION not yet supported");
+               return result;
+       }
+
+       result = palloc(size);
+       result[0] = '\0';
+
+       inspected = lwgeom_inspect(SERIALIZED_FORM(geometry));
+       for(t=0; t<inspected->ngeometries; t++)
+       {
+               char *subgeom = lwgeom_getsubgeometry_inspected(inspected, t);
+               LWPOINT *point;
+               LWLINE *line;
+               LWPOLY *poly;
+
+               if (lwgeom_getType(subgeom[0]) == POINTTYPE)
+               {
+                       point = lwpoint_deserialize(subgeom);
+                       size +=MAX_DIGS_DOUBLE*3 + 2 +10  ;
+                       //make memory bigger
+                       result = repalloc(result, size );
+
+                       if (t) strcat(result, ",");
+
+                       pt = (POINT2D *)getPoint(point->point, 0);
+                       if (svgrel == 1)
+                       {  
+                               //render circle
+                               print_svg_coords(result, pt, precision);
+                       }
+                       else
+                       {  
+                               //render circle
+                               print_svg_circle(result, pt, precision);
+                       }
+
+               }
+               if (lwgeom_getType(subgeom[0]) == LINETYPE)
+               {
+                       line = lwline_deserialize(subgeom);
+
+                       size +=(MAX_DIGS_DOUBLE*3+5)*line->points->npoints+12+3;
+                       result = repalloc(result, size);
+
+                       // start path with moveto
+                       strcat(result, "M ");
+
+                       if (svgrel == 1)
+                               print_svg_path_rel(result, line->points,
+                                       precision);
+                       else
+                               print_svg_path_abs( result, line->points,
+                                       precision);
+
+                       strcat(result, " ");
+               }
+               if (lwgeom_getType(subgeom[0]) == POLYGONTYPE)
+               {
+                       poly = lwpoly_deserialize(subgeom);
+
+                       npts = 0;
+                       for (u=0; u<poly->nrings; u++)
+                               npts += poly->rings[u]->npoints;
+
+                       size += (MAX_DIGS_DOUBLE*3+3) * npts +
+                               5 * poly->nrings;
+                       result = repalloc(result, size);
+
+                       for (u=0; u<poly->nrings; u++)  //for each ring
+                       {
+                               strcat(result,"M ");    //begin ring
+                               if (svgrel == 1)
+                                       print_svg_path_rel(result, 
+                                               poly->rings[u],
+                                               precision);
+                               else
+                                       print_svg_path_abs(result,
+                                               poly->rings[u],
+                                               precision);
+                               
+                               strcat(result," ");     //end ring
+                       }
+               }
+       }
+       return(result);
+}
+
+
+void print_svg_coords(char *result, POINT2D *pt, int precision)
+{
+       char    temp[MAX_DIGS_DOUBLE*3+12];
+
+       if ( (pt == NULL) || (result == NULL) )
+               return;
+
+       sprintf(temp, "x=\"%.*g\" y=\"%.*g\"", 
+                       precision, pt->x, 
+                       precision, pt->y*-1);
+       strcat(result,temp);
+}
+
+
+void print_svg_circle(char *result, POINT2D *pt, int precision)
+{
+       char    temp[MAX_DIGS_DOUBLE*3 +12];
+
+       if ( (pt == NULL) || (result == NULL) )
+               return;
+
+       sprintf(temp, "cx=\"%.*g\" cy=\"%.*g\"", 
+                       precision, pt->x, 
+                       precision, pt->y*-1);
+       strcat(result,temp);
+}
+
+
+void
+print_svg_path_abs(char *result, POINTARRAY *pa, int precision)
+{
+       int u;
+       POINT2D *pt;
+
+       result += strlen(result);
+       for (u=0; u<pa->npoints; u++)
+       {
+               pt = (POINT2D *)getPoint(pa, u);
+               if (u != 0)
+               {
+                       result[0] = ' ';
+                       result++;
+               }
+               result+= sprintf(result,"%.*g %.*g", 
+                               precision, pt->x, 
+                               precision, pt->y*-1);
+       }
+}
+
+
+void
+print_svg_path_rel(char *result, POINTARRAY *pa, int precision)
+{
+       int u;
+       POINT2D *pt, *lpt;
+
+       result += strlen(result);
+
+       pt = (POINT2D *)getPoint(pa, 0);
+       result += sprintf(result,"%.*g %.*g l", 
+               precision, pt->x, 
+               precision, pt->y*-1);
+
+       lpt = pt;
+       for (u=1; u<pa->npoints; u++)
+       {
+               pt = (POINT2D *)getPoint(pa, u);
+               result+= sprintf(result," %.*g %.*g", 
+                               precision, (pt->x-lpt->x), 
+                               precision, (pt->y-lpt->y)*-1);
+               lpt = pt;
+       }
+}
+
+
+/**********************************************************************
+ * $Log$
+ * Revision 1.1  2004/09/13 13:32:01  strk
+ * Added AsSVG().
+ *
+ **********************************************************************/
+
index 92110b8ccf1cc6d8987e09e81766f302bd3a8155..63214509356976263d139a1178a5bb1a338d60e4 100644 (file)
@@ -2878,6 +2878,25 @@ CREATEFUNCTION Equals(geometry,geometry)
        AS '@MODULE_FILENAME@','geomequals'
        LANGUAGE 'C' WITH (isstrict,iscachable);
 
+-----------------------------------------------------------------------
+-- SVG OUTPUT
+-----------------------------------------------------------------------
+CREATEFUNCTION AsSvg(geometry,int4,int4)
+       RETURNS TEXT
+       AS '@MODULE_FILENAME@','assvg_geometry'
+       LANGUAGE 'C';
+
+CREATEFUNCTION AsSvg(geometry,int4)
+       RETURNS TEXT
+       AS '@MODULE_FILENAME@','assvg_geometry'
+       LANGUAGE 'C';
+
+CREATEFUNCTION AsSvg(geometry)
+       RETURNS TEXT
+       AS '@MODULE_FILENAME@','assvg_geometry'
+       LANGUAGE 'C';
+
+
 ---------------------------------------------------------------
 -- END
 ---------------------------------------------------------------