From: Sandro Santilli Date: Fri, 10 Sep 2004 12:49:29 +0000 (+0000) Subject: Included SVG output function, modified to have precision expressed X-Git-Tag: pgis_1_0_0RC1~468 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=082b3497d00d013dfb8399cb22a70fa68a0694af;p=postgis Included SVG output function, modified to have precision expressed in terms of significant digits. git-svn-id: http://svn.osgeo.org/postgis/trunk@796 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/Makefile b/Makefile index 14dbdf761..b4bbb5b07 100644 --- 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 diff --git a/postgis.sql.in b/postgis.sql.in index 4a86b5f47..8c0930897 100644 --- a/postgis.sql.in +++ b/postgis.sql.in @@ -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 index 000000000..5313d733b --- /dev/null +++ b/postgis_svg.c @@ -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 + * Patches from: Olivier Courtin + **********************************************************************/ + +#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;tnobjs; 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