]> granicus.if.org Git - postgis/commitdiff
Included SVG output function, modified to have precision expressed
authorSandro Santilli <strk@keybit.net>
Fri, 10 Sep 2004 12:49:29 +0000 (12:49 +0000)
committerSandro Santilli <strk@keybit.net>
Fri, 10 Sep 2004 12:49:29 +0000 (12:49 +0000)
in terms of significant digits.

git-svn-id: http://svn.osgeo.org/postgis/trunk@796 b70326c6-7e19-0410-871a-916f4a2858ee

Makefile
postgis.sql.in
postgis_svg.c [new file with mode: 0644]

index 14dbdf76186d822f1a41871e41d53ffbe22adcf5..b4bbb5b07b1a45267faac4de92e5f6e8596e5668 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -167,7 +167,7 @@ ifeq ($(USE_GEOS),1)
        GEOS_WRAPPER=postgis_geos_wrapper.o
 endif
 
-OBJS=postgis_debug.o postgis_ops.o postgis_fn.o postgis_inout.o postgis_proj.o postgis_chip.o postgis_transform.o postgis_gist_$(GIST_SUPPORT).o $(GIST_ESTIMATE) postgis_geos.o $(GEOS_WRAPPER) postgis_algo.o
+OBJS=postgis_debug.o postgis_ops.o postgis_fn.o postgis_inout.o postgis_proj.o postgis_chip.o postgis_transform.o postgis_svg.o postgis_gist_$(GIST_SUPPORT).o $(GIST_ESTIMATE) postgis_geos.o $(GEOS_WRAPPER) postgis_algo.o
 
 #---------------------------------------------------------------
 # Add libraries that libpq depends (or might depend) on into the
index 4a86b5f47da0f893daaaff9cba43e5d62387d3c7..8c0930897f71663784d65be1e18418458d7ee982 100644 (file)
@@ -2774,4 +2774,23 @@ CREATEFUNCTION estimate_histogram2d(HISTOGRAM2D,box)
        AS '@MODULE_FILENAME@','estimate_histogram2d'
        LANGUAGE 'C'  with (isstrict);
 
+
+-----------------------------------------------------------------------
+-- 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 TRANSACTION;
diff --git a/postgis_svg.c b/postgis_svg.c
new file mode 100644 (file)
index 0000000..5313d73
--- /dev/null
@@ -0,0 +1,332 @@
+/**********************************************************************
+ * $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 "postgis.h"
+
+Datum assvg_geometry(PG_FUNCTION_ARGS);
+char *geometry_to_svg(GEOMETRY  *geometry, int svgrel, int precision);
+void print_svg_coords(char *result, POINT3D *pt, int precision);
+void print_svg_circle(char *result, POINT3D *pt, int precision);
+void print_svg_path_abs(char *result, POINT3D *pt ,int npoints, int
+precision); void print_svg_path_rel(char *result, POINT3D *pt ,int
+npoints, 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)
+{
+       GEOMETRY *geom1;
+       char *wkt;
+       char *result;
+       int len;
+       int32 svgrel=0;
+       int32 precision=15;
+
+       if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
+
+       geom1 = (GEOMETRY *)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);
+               
+       wkt = geometry_to_svg(geom1, svgrel, precision);
+
+       len = strlen(wkt) + 5;
+
+       result= palloc(len);
+       *((int *) result) = len;
+
+       memcpy(result +4, wkt, len-4);
+
+       pfree(wkt);
+
+       PG_RETURN_CSTRING(result);
+}
+
+
+//takes a GEOMETRY and returns a SVG representation
+char *geometry_to_svg(GEOMETRY  *geometry, int svgrel, int precision)
+{
+       char            *result;
+       int             t,u;
+       int32           *offsets;
+       char            *obj;
+       POINT3D *pts;
+       POLYGON3D       *polygon;
+       LINE3D  *line;
+       POINT3D *point;
+
+       int             pt_off,size;
+       bool            first_sub_obj = TRUE;
+       int             mem_size,npts;
+
+       //elog(NOTICE, "precision is %d", precision);
+
+       size = 30;      //just enough to put in object type
+       //try to limit number of repalloc()s
+       result = (char *) palloc(30); mem_size= 30;
+
+       // TODO BBox, from where is it called?...
+       if (geometry->type == BBOXONLYTYPE)
+       {
+               if (svgrel == 1)
+               {
+                       // 5 double digits+ "Mhvhz"+ spaces +null
+                       mem_size = MAX_DIGS_DOUBLE*5+5+6+1;
+                       pfree(result);
+                       result = (char *) palloc(mem_size); 
+
+                       sprintf(result, "M %.*g %.*g h%.*g v%.*g h%.*g z",
+                               precision, 
+                               geometry->bvol.LLB.x,
+                               precision, 
+                               geometry->bvol.URT.y*-1,
+                               precision, 
+                               (geometry->bvol.URT.x 
+                                - geometry->bvol.LLB.x),
+                               precision, 
+                               (geometry->bvol.URT.y 
+                                - geometry->bvol.LLB.y),
+                               precision, 
+                               (geometry->bvol.URT.x 
+                                - geometry->bvol.LLB.x)*-1);
+               }
+               else
+               {
+                       mem_size = MAX_DIGS_DOUBLE*4+3+1;
+                       pfree(result);
+                       result = (char *) palloc(mem_size); 
+                       // 4 double digits + 3 spaces +null
+
+                       sprintf(result, "%.*g %.*g %.*g %.*g",
+                               precision,
+                               geometry->bvol.LLB.x,
+                               precision,
+                               geometry->bvol.URT.y*-1,
+                               precision,
+                               (geometry->bvol.URT.x - 
+geometry->bvol.LLB.x),
+                               precision, 
+                               (geometry->bvol.URT.y - 
+geometry->bvol.LLB.y)
+                               );
+               }
+               return result;
+       }
+
+       // no more warnings on compiletime
+       sprintf(result,"%s", "");
+
+       if (geometry->type == COLLECTIONTYPE)
+       {
+               sprintf(result, "GEOMETRYCOLLECTION not yet supported");
+               return result;
+       }
+
+       //where are the objects?
+       offsets = (int32 *) ( ((char *) &(geometry->objType[0] ))
+                       + sizeof(int32) * geometry->nobjs ) ;
+
+       for(t=0;t<geometry->nobjs; t++)  //for each object
+       {
+               obj = (char *) geometry +offsets[t] ;
+
+               if (geometry->objType[t] == 1)   //POINT
+               {
+                       point = (POINT3D *) obj;
+                       size +=MAX_DIGS_DOUBLE*3 + 2 +10  ;
+                       //make memory bigger
+                       result = repalloc(result, size );
+
+                       if (!(first_sub_obj))
+                       {       
+                               // next circle ...
+                               strcat(result,",");
+                       }
+                       else
+                       {
+                               first_sub_obj = FALSE;
+                       }
+                       if (svgrel == 1)
+                       {  
+                               //render circle
+                               print_svg_coords(result, point, precision);
+                       }
+                       else
+                       {  
+                               //render circle
+                               print_svg_circle(result, point, precision);
+                       }
+
+               }
+               if (geometry->objType[t] == 2)  //LINESTRING
+               {
+                       line = (LINE3D *) obj;
+
+                       size +=(MAX_DIGS_DOUBLE*3+5)*line->npoints +12+3;
+                       result = repalloc(result, size );
+
+                       // start path with moveto
+                       strcat(result, "M ");
+
+                       if (svgrel == 1)
+                               print_svg_path_rel(
+                                               result,
+                                               &line->points[0],
+                                               line->npoints, 
+                                               precision
+                                               );
+                       else
+                               print_svg_path_abs(
+                                               result,
+                                               &line->points[0],
+                                               line->npoints,
+                                               precision
+                                               );
+
+                       strcat(result," ");
+               }
+               if (geometry->objType[t] == 3)  //POLYGON
+               {
+                       polygon = (POLYGON3D *) obj;
+                       pt_off = 0;     //where is the first point in this ring?
+
+                       //where are the points
+                       pts = (POINT3D *)
+                               ((char *)&(polygon->npoints[polygon->nrings]));
+                       pts = (POINT3D *) MAXALIGN(pts);
+
+                       npts = 0;
+                       for (u=0; u< polygon->nrings ; u++)
+                               npts += polygon->npoints[u];
+
+                       size += (MAX_DIGS_DOUBLE*3+3) 
+                               * npts + 5* polygon->nrings;
+                       result = repalloc(result, size );
+
+                       for (u=0; u< polygon->nrings ; u++)  //for each ring
+                       {
+                               strcat(result,"M ");    //begin ring
+                               if (svgrel == 1)
+                                       print_svg_path_rel(result, 
+                                                       &pts[pt_off] ,
+                                                       polygon->npoints[u],
+                                                       precision);
+                               else
+                                       print_svg_path_abs(result,
+                                                       &pts[pt_off],
+                                                       polygon->npoints[u],
+                                                       precision);
+                               
+                               //where is first point of next ring?
+                               pt_off = pt_off + polygon->npoints[u]; 
+                               strcat(result," ");     //end ring
+                       }
+               }
+       }
+       return(result);
+}
+
+
+void print_svg_coords(char *result, POINT3D *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, POINT3D *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, POINT3D *pt ,int npoints, int
+precision){
+       int     u;
+
+       result += strlen(result);
+       for (u=0;u<npoints;u++)
+       {
+               if (u != 0)
+               {
+                       result[0] = ' ';
+                       result++;
+               }
+               result+= sprintf(result,"%.*g %.*g", 
+                               precision, pt[u].x, 
+                               precision, pt[u].y*-1);
+       }
+}
+
+
+void print_svg_path_rel(char *result, POINT3D *pt ,int npoints, int
+precision){
+       int     u;
+
+       result += strlen(result);
+       for (u=0;u<npoints;u++)
+       {
+               if (u == 0)
+               {
+                       result+= sprintf(result,"%.*g %.*g l", 
+                                       precision, pt[u].x, 
+                                       precision, pt[u].y*-1);
+               }
+               else
+               {
+                       result+= sprintf(result," %.*g %.*g", 
+                                       precision, (pt[u].x-pt[u-1].x), 
+                                       precision, (pt[u].y-pt[u-1].y)*-1);
+               }
+       }
+}
+
+
+/**********************************************************************
+ * $Log$
+ * Revision 1.1  2004/09/10 12:49:29  strk
+ * Included SVG output function, modified to have precision expressed
+ * in terms of significant digits.
+ *
+ **********************************************************************/
+