[postgis-commits] svn - r3813 - trunk/postgis
postgis-commits at postgis.refractions.net
postgis-commits at postgis.refractions.net
Mon Mar 9 07:51:43 PDT 2009
Author: colivier
Date: 2009-03-09 07:51:42 -0700 (Mon, 09 Mar 2009)
New Revision: 3813
Modified:
trunk/postgis/lwgeom_svg.c
Log:
Refactored the whole assvg export function in the same way than asgeojson. Fix #119 issue on big geometrycollection geometry. Keep the same SVG output than before
Modified: trunk/postgis/lwgeom_svg.c
===================================================================
--- trunk/postgis/lwgeom_svg.c 2009-03-09 14:36:15 UTC (rev 3812)
+++ trunk/postgis/lwgeom_svg.c 2009-03-09 14:51:42 UTC (rev 3813)
@@ -12,7 +12,7 @@
*
* SVG output routines.
* Originally written by: Klaus Förster <klaus at svg.cc>
- * Patches from: Olivier Courtin <pnine at free.fr>
+ * Refactored by: Olivier Courtin (Camptocamp)
*
**********************************************************************/
@@ -22,15 +22,24 @@
#include "liblwgeom.h"
Datum assvg_geometry(PG_FUNCTION_ARGS);
-char *geometry_to_svg(PG_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, int polygonRing);
-void print_svg_path_rel(char *result, POINTARRAY *pa, int precision, int polygonRing);
+char *geometry_to_svg(uchar *srl, bool relative, int precision);
+static char * assvg_point(LWPOINT *point, bool relative, int precision);
+static char * assvg_line(LWLINE *line, bool relative, int precision);
+static char * assvg_polygon(LWPOLY *poly, bool relative, int precision);
+static char * assvg_multipoint(LWGEOM_INSPECTED *insp, bool relative, int precision);
+static char * assvg_multiline(LWGEOM_INSPECTED *insp, bool relative, int precision);
+static char * assvg_multipolygon(LWGEOM_INSPECTED *insp, bool relative, int precision);
+static char * assvg_collection(LWGEOM_INSPECTED *insp, bool relative, int precision);
+static size_t assvg_inspected_size(LWGEOM_INSPECTED *insp, bool relative, int precision);
+static size_t assvg_inspected_buf(LWGEOM_INSPECTED *insp, char *output, bool relative, int precision);
+static size_t pointArray_svg_size(POINTARRAY *pa, int precision);
+static size_t pointArray_svg_rel(POINTARRAY *pa, char * output, bool close_ring, int precision);
+static size_t pointArray_svg_abs(POINTARRAY *pa, char * output, bool close_ring, int precision);
+
#define SHOW_DIGS_DOUBLE 15
#define MAX_DOUBLE_PRECISION 15
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
+#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 2) /* +2 mean add dot and sign */
/**
* SVG features
@@ -42,8 +51,8 @@
char *svg;
text *result;
int len;
- int32 svgrel=0;
- int32 precision=MAX_DOUBLE_PRECISION;
+ bool relative = false;
+ int precision=MAX_DOUBLE_PRECISION;
if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
@@ -51,7 +60,7 @@
/* check for relative path notation */
if ( PG_NARGS() > 1 && ! PG_ARGISNULL(1) )
- svgrel = PG_GETARG_INT32(1);
+ relative = PG_GETARG_INT32(1) ? true:false;
if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
{
@@ -61,18 +70,15 @@
else if ( precision < 0 ) precision = 0;
}
- svg = geometry_to_svg(geom, svgrel, precision);
- if ( ! svg ) PG_RETURN_NULL();
+ svg = geometry_to_svg(SERIALIZED_FORM(geom), relative, precision);
+ PG_FREE_IF_COPY(geom, 0);
len = strlen(svg) + VARHDRSZ;
-
result = palloc(len);
SET_VARSIZE(result, len);
-
memcpy(VARDATA(result), svg, len-VARHDRSZ);
pfree(svg);
- PG_FREE_IF_COPY(geom, 0);
PG_RETURN_POINTER(result);
}
@@ -80,324 +86,581 @@
/*takes a GEOMETRY and returns a SVG representation */
char *
-geometry_to_svg(PG_LWGEOM *geometry, int svgrel, int precision)
+geometry_to_svg(uchar *geom, bool relative, int precision)
{
- char *result = NULL;
- LWGEOM_INSPECTED *inspected;
- int t,u;
- POINT2D pt;
- int npts;
- int size;
+ char *ret = NULL;
+ int type;
- /*elog(NOTICE, "precision is %d", precision); */
- size = 30; /*just enough to put in object type */
+ type = lwgeom_getType(geom[0]);
+ switch (type)
+ {
+ case POINTTYPE:
+ ret = assvg_point(lwpoint_deserialize(geom), relative, precision);
+ break;
+ case LINETYPE:
+ ret = assvg_line(lwline_deserialize(geom), relative, precision);
+ break;
+ case POLYGONTYPE:
+ ret = assvg_polygon(lwpoly_deserialize(geom), relative, precision);
+ break;
+ case MULTIPOINTTYPE:
+ ret = assvg_multipoint(lwgeom_inspect(geom), relative, precision);
+ break;
+ case MULTILINETYPE:
+ ret = assvg_multiline(lwgeom_inspect(geom), relative, precision);
+ break;
+ case MULTIPOLYGONTYPE:
+ ret = assvg_multipolygon(lwgeom_inspect(geom), relative, precision);
+ break;
+ case COLLECTIONTYPE:
+ ret = assvg_collection(lwgeom_inspect(geom), relative, precision);
+ break;
- if (lwgeom_getType(geometry->type) == COLLECTIONTYPE)
- {
- LWCOLLECTION* theCollection = lwcollection_deserialize(SERIALIZED_FORM(geometry));
+ default: lwerror("ST_AsSVG: '%s' geometry type not supported.",
+ lwgeom_typename(type));
+ }
- PG_LWGEOM* theGeom;
- char* geomSvg;
- int i;
+ return ret;
+}
- for(i = 0; i < theCollection->ngeoms; ++i)
- {
- theGeom = pglwgeom_serialize(theCollection->geoms[i]);
- if(!theGeom)
- {
- pfree(result);
- return NULL;
- }
- geomSvg = geometry_to_svg(theGeom, svgrel, precision);
- size += strlen(geomSvg + 1);
-
- if(!geomSvg)
- {
- pfree(result);
- return NULL;
- }
+/*
+ * Point Geometry
+ */
- if(i == 0)
- {
- result = geomSvg;
- }
- else
- {
- result = repalloc(result, size);
- strcat(result, ";");
- strncat(result, geomSvg, strlen(geomSvg));
- pfree(geomSvg);
- }
- pfree(theGeom);
- }
- return result;
+static size_t
+assvg_point_size(LWPOINT *point, bool circle, int precision)
+{
+ size_t size;
+
+ size = (MAX_DIGS_DOUBLE + precision) * 2;
+ if (circle) size += sizeof("cx='' cy=''");
+ else size += sizeof("x='' y=''");
+
+ return size;
+}
+
+static size_t
+assvg_point_buf(LWPOINT *point, char * output, bool circle, int precision)
+{
+ char *ptr=output;
+ char x[MAX_DIGS_DOUBLE+3];
+ char y[MAX_DIGS_DOUBLE+3];
+ POINT2D pt;
+
+ getPoint2d_p(point->point, 0, &pt);
+ sprintf(x, "%.*f", precision, pt.x);
+ trim_trailing_zeros(x);
+ /* SVG Y axis is reversed, an no need to transform 0 into -0 */
+ sprintf(y, "%.*f", precision, fabs(pt.y) ? pt.y * -1 : pt.y);
+ trim_trailing_zeros(y);
+
+ if (circle) ptr += sprintf(ptr, "x=\"%s\" y=\"%s\"", x, y);
+ else ptr += sprintf(ptr, "cx=\"%s\" cy=\"%s\"", x, y);
+
+ return (ptr-output);
+}
+
+static char *
+assvg_point(LWPOINT *point, bool circle, int precision)
+{
+ char *output;
+ int size;
+
+ size = assvg_point_size(point, circle, precision);
+ output = palloc(size);
+ assvg_point_buf(point, output, circle, precision);
+
+ return output;
+}
+
+
+/*
+ * Line Geometry
+ */
+
+static size_t
+assvg_line_size(LWLINE *line, bool relative, int precision)
+{
+ size_t size;
+
+ size = sizeof("M ");
+ size += pointArray_svg_size(line->points, precision);
+ return size;
+}
+
+static size_t
+assvg_line_buf(LWLINE *line, char * output, bool relative, int precision)
+{
+ char *ptr=output;
+
+ /* Start path with SVG MoveTo */
+ ptr += sprintf(ptr, "M ");
+ if (relative)
+ ptr += pointArray_svg_rel(line->points, ptr, true, precision);
+ else
+ ptr += pointArray_svg_abs(line->points, ptr, true, precision);
+
+ return (ptr-output);
+}
+
+static char *
+assvg_line(LWLINE *line, bool relative, int precision)
+{
+ char *output;
+ int size;
+
+ size = assvg_line_size(line, relative, precision);
+ output = palloc(size);
+ assvg_line_buf(line, output, relative, precision);
+
+ return output;
+}
+
+
+/*
+ * Polygon Geometry
+ */
+
+static size_t
+assvg_polygon_size(LWPOLY *poly, bool relative, int precision)
+{
+ int i;
+ size_t size=0;
+
+ for (i=0; i<poly->nrings; i++)
+ size += pointArray_svg_size(poly->rings[i], precision);
+ size += sizeof(" M Z") * poly->nrings;
+
+ return size;
+}
+
+static size_t
+assvg_polygon_buf(LWPOLY *poly, char * output, bool relative, int precision)
+{
+ int i;
+ char *ptr=output;
+
+ for (i=0; i<poly->nrings; i++) {
+ if (i) ptr += sprintf(ptr, " "); /* Space beetween each ring */
+ ptr += sprintf(ptr, "M "); /* Start path with SVG MoveTo */
+
+ if (relative) {
+ ptr += pointArray_svg_rel(poly->rings[i], ptr, false, precision);
+ ptr += sprintf(ptr, " z"); /* SVG closepath */
+ } else {
+ ptr += pointArray_svg_abs(poly->rings[i], ptr, false, precision);
+ ptr += sprintf(ptr, " Z"); /* SVG closepath */
+ }
}
- result = palloc(size);
- result[0] = '\0';
+ return (ptr-output);
+}
- inspected = lwgeom_inspect(SERIALIZED_FORM(geometry));
- for(t=0; t<inspected->ngeometries; t++)
- {
- uchar *subgeom = lwgeom_getsubgeometry_inspected(inspected, t);
- LWPOINT *point;
- LWLINE *line;
- LWPOLY *poly;
+static char *
+assvg_polygon(LWPOLY *poly, bool relative, int precision)
+{
+ char *output;
+ int size;
- if (lwgeom_getType(subgeom[0]) == POINTTYPE)
- {
- point = lwpoint_deserialize(subgeom);
- size +=MAX_DIGS_DOUBLE*3 + 2 +10 ;
- /*make memory bigger */
- result = repalloc(result, size );
+ size = assvg_polygon_size(poly, relative, precision);
+ output = palloc(size);
+ assvg_polygon_buf(poly, output, relative, precision);
- if (t) strcat(result, ",");
+ return output;
+}
- getPoint2d_p(point->point, 0, &pt);
- 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);
+/*
+ * Multipoint Geometry
+ */
- size +=(MAX_DIGS_DOUBLE*3+5)*line->points->npoints+12+3;
- result = repalloc(result, size);
+static size_t
+assvg_multipoint_size(LWGEOM_INSPECTED *insp, bool relative, int precision)
+{
+ LWPOINT *point;
+ size_t size=0;
+ int i;
- if(t)
- {
- strcat(result, " ");
- }
+ for (i=0 ; i<insp->ngeometries ; i++) {
+ point = lwgeom_getpoint_inspected(insp, i);
+ size += assvg_point_size(point, relative, precision);
+ /* lwpoint_release(point); */
+ }
+ size += sizeof(" ") * --i; /* Arbitrary comma separator */
- /* start path with moveto */
- strcat(result, "M ");
+ return size;
+}
- if (svgrel == 1)
- print_svg_path_rel(result, line->points,
- precision, 0);
- else
- print_svg_path_abs( result, line->points,
- precision, 0);
- }
- if (lwgeom_getType(subgeom[0]) == POLYGONTYPE)
- {
- poly = lwpoly_deserialize(subgeom);
+static size_t
+assvg_multipoint_buf(LWGEOM_INSPECTED *insp, char *output, bool relative, int precision)
+{
+ LWPOINT *point;
+ int i;
+ char *ptr=output;
- npts = 0;
- for (u=0; u<poly->nrings; u++)
- npts += poly->rings[u]->npoints;
+ for (i=0 ; i<insp->ngeometries ; i++)
+ {
+ if (i) ptr += sprintf(ptr, ","); /* Arbitrary comma separator */
+ point = lwgeom_getpoint_inspected(insp, i);
+ ptr += assvg_point_buf(point, ptr, relative, precision);
+ if (point) lwpoint_release(point);
+ }
- size += (MAX_DIGS_DOUBLE*3+3) * npts +
- 5 * poly->nrings + 1;
- result = repalloc(result, size);
+ return (ptr-output);
+}
- if(t)
- {
- strcat(result, " ");
- }
+static char *
+assvg_multipoint(LWGEOM_INSPECTED *point, bool relative, int precision)
+{
+ char *output;
+ int size;
- for (u=0; u<poly->nrings; u++) /*for each ring */
- {
- if(u)
- {
- strcat(result," "); /*Blank separator from previous ring*/
- }
+ size = assvg_multipoint_size(point, relative, precision);
+ output = palloc(size);
+ assvg_multipoint_buf(point, output, relative, precision);
- strcat(result,"M "); /*begin ring */
- if (svgrel == 1)
- print_svg_path_rel(result,
- poly->rings[u],
- precision, 1);
- else
- print_svg_path_abs(result,
- poly->rings[u],
- precision, 1);
- }
- }
+ return output;
+}
+
+
+/*
+ * Multiline Geometry
+ */
+
+static size_t
+assvg_multiline_size(LWGEOM_INSPECTED *insp, bool relative, int precision)
+{
+ LWLINE *line;
+ size_t size=0;
+ int i;
+
+ for (i=0 ; i<insp->ngeometries ; i++) {
+ line = lwgeom_getline_inspected(insp, i);
+ size += assvg_line_size(line, relative, precision);
+ if (line) lwline_release(line);
}
- return(result);
+ size += sizeof(" ") * --i; /* SVG whitespace Separator */
+
+ return size;
}
+static size_t
+assvg_multiline_buf(LWGEOM_INSPECTED *insp, char *output, bool relative, int precision)
+{
+ LWLINE *line;
+ int i;
+ char *ptr=output;
-void print_svg_coords(char *result, POINT2D *pt, int precision)
+ for (i=0 ; i<insp->ngeometries ; i++)
+ {
+ if (i) ptr += sprintf(ptr, " "); /* SVG whitespace Separator */
+ line = lwgeom_getline_inspected(insp, i);
+ ptr += assvg_line_buf(line, ptr, relative, precision);
+ if (line) lwline_release(line);
+ }
+
+ return (ptr-output);
+}
+
+static char *
+assvg_multiline(LWGEOM_INSPECTED *line, bool relative, int precision)
{
- char temp[MAX_DIGS_DOUBLE*3+12];
- char x[MAX_DIGS_DOUBLE+3];
- char y[MAX_DIGS_DOUBLE+3];
+ char *output;
+ int size;
- if ( (pt == NULL) || (result == NULL) )
- return;
+ size = assvg_multiline_size(line, relative, precision);
+ output = palloc(size);
+ assvg_multiline_buf(line, output, relative, precision);
- sprintf(x, "%.*f", precision, pt->x);
- trim_trailing_zeros(x);
- sprintf(y, "%.*f", precision, fabs(pt->y) > 0 ? (pt->y * -1) : pt->y);
- trim_trailing_zeros(y);
+ return output;
+}
- sprintf(temp, "x=\"%s\" y=\"%s\"", x, y);
- strcat(result,temp);
+
+/*
+ * Multipolygon Geometry
+ */
+
+static size_t
+assvg_multipolygon_size(LWGEOM_INSPECTED *insp, bool relative, int precision)
+{
+ LWPOLY *poly;
+ size_t size=0;
+ int i;
+
+ for (i=0 ; i<insp->ngeometries ; i++) {
+ poly = lwgeom_getpoly_inspected(insp, i);
+ size += assvg_polygon_size(poly, relative, precision);
+ /* lwpoly_release(poly); */
+ }
+ size += sizeof(" ") * --i; /* SVG whitespace Separator */
+
+ return size;
}
+static size_t
+assvg_multipolygon_buf(LWGEOM_INSPECTED *insp, char *output, bool relative, int precision)
+{
+ LWPOLY *poly;
+ int i;
+ char *ptr=output;
-void print_svg_circle(char *result, POINT2D *pt, int precision)
+ for (i=0 ; i<insp->ngeometries ; i++)
+ {
+ if (i) ptr += sprintf(ptr, " "); /* SVG whitespace Separator */
+ poly = lwgeom_getpoly_inspected(insp, i);
+ ptr += assvg_polygon_buf(poly, ptr, relative, precision);
+ /* lwpoly_release(poly); */
+ }
+
+ return (ptr-output);
+}
+
+static char *
+assvg_multipolygon(LWGEOM_INSPECTED *poly, bool relative, int precision)
{
- char temp[MAX_DIGS_DOUBLE*3 +12];
- char x[MAX_DIGS_DOUBLE+3];
- char y[MAX_DIGS_DOUBLE+3];
+ char *output;
+ int size;
- if ( (pt == NULL) || (result == NULL) )
- return;
+ size = assvg_multipolygon_size(poly, relative, precision);
+ output = palloc(size);
+ assvg_multipolygon_buf(poly, output, relative, precision);
- sprintf(x, "%.*f", precision, pt->x);
- trim_trailing_zeros(x);
- sprintf(y, "%.*f", precision, fabs(pt->y) > 0 ? (pt->y * -1) : pt->y);
- trim_trailing_zeros(y);
+ return output;
+}
- sprintf(temp, "cx=\"%s\" cy=\"%s\"", x, y);
- strcat(result,temp);
+
+ /*
+ * Collection Geometry
+ */
+
+static size_t
+assvg_collection_size(LWGEOM_INSPECTED *insp, bool relative, int precision)
+{
+ int i;
+ size_t size=0;
+ LWGEOM_INSPECTED *subinsp;
+ uchar *subgeom;
+
+ for (i=0; i<insp->ngeometries; i++)
+ {
+ subgeom = lwgeom_getsubgeometry_inspected(insp, i);
+ subinsp = lwgeom_inspect(subgeom);
+ size += assvg_inspected_size(subinsp, relative, precision);
+ lwinspected_release(subinsp);
+ }
+ size += sizeof(";") * --i;
+
+ return size;
}
+static size_t
+assvg_collection_buf(LWGEOM_INSPECTED *insp, char *output, bool relative, int precision)
+{
+ int i;
+ char *ptr=output;
+ LWGEOM_INSPECTED *subinsp;
+ uchar *subgeom;
-void
-print_svg_path_abs(char *result, POINTARRAY *pa, int precision, int polygonRing)
+ for (i=0; i<insp->ngeometries; i++)
+ {
+ if (i) ptr += sprintf(ptr, ";");
+ subgeom = lwgeom_getsubgeometry_inspected(insp, i);
+ subinsp = lwgeom_inspect(subgeom);
+ ptr += assvg_inspected_buf(subinsp, ptr, relative, precision);
+ lwinspected_release(subinsp);
+ }
+
+ return (ptr - output);
+}
+
+static char *
+assvg_collection(LWGEOM_INSPECTED *insp, bool relative, int precision)
{
- int u;
- POINT2D pt;
- char x[MAX_DIGS_DOUBLE+3];
- char y[MAX_DIGS_DOUBLE+3];
+ char *output;
+ int size;
- result += strlen(result);
- for (u=0; u<pa->npoints; u++)
- {
- getPoint2d_p(pa, u, &pt);
-
- /* close PATH with 'Z' for polygon rings if last point equals first point */
- if(u > 0 && u == (pa->npoints - 1) && polygonRing)
- {
- POINT2D firstPoint;
- getPoint2d_p(pa, 0, &firstPoint);
- if(pt.x == firstPoint.x && pt.y == firstPoint.y)
- {
- sprintf(result, " Z");
- break;
- }
- }
+ size = assvg_collection_size(insp, relative, precision);
+ output = palloc(size);
+ assvg_collection_buf(insp, output, relative, precision);
- if (u != 0)
- {
- result[0] = ' ';
- result++;
- }
+ return output;
+}
- sprintf(x, "%.*f", precision, pt.x);
- trim_trailing_zeros(x);
- sprintf(y, "%.*f", precision, fabs(pt.y) > 0.0 ? (pt.y * -1) : pt.y);
- trim_trailing_zeros(y);
- result+= sprintf(result,"%s %s", x, y);
- }
+
+
+static size_t
+assvg_inspected_buf(LWGEOM_INSPECTED *insp, char *output, bool relative, int precision)
+{
+ LWPOINT *point;
+ LWLINE *line;
+ LWPOLY *poly;
+ int type = lwgeom_getType(insp->serialized_form[0]);
+ char *ptr=output;
+
+ switch(type) {
+ case POINTTYPE:
+ point=lwgeom_getpoint_inspected(insp, 0);
+ ptr += assvg_point_buf(point, ptr, relative, precision);
+ lwpoint_release(point);
+ break;
+
+ case LINETYPE:
+ line=lwgeom_getline_inspected(insp, 0);
+ ptr += assvg_line_buf(line, ptr, relative, precision);
+ lwline_release(line);
+ break;
+
+ case POLYGONTYPE:
+ poly=lwgeom_getpoly_inspected(insp, 0);
+ ptr += assvg_polygon_buf(poly, ptr, relative, precision);
+ lwpoly_release(poly);
+ break;
+
+ case MULTIPOINTTYPE:
+ ptr += assvg_multipoint_buf(insp, ptr, relative, precision);
+ break;
+
+ case MULTILINETYPE:
+ ptr += assvg_multiline_buf(insp, ptr, relative, precision);
+ break;
+
+ case MULTIPOLYGONTYPE:
+ ptr += assvg_multipolygon_buf(insp, ptr, relative, precision);
+ break;
+
+ default: lwerror("ST_AsSVG: '%s' geometry type not supported.",
+ lwgeom_typename(type));
+ }
+
+ return (ptr-output);
}
-void
-print_svg_path_rel(char *result, POINTARRAY *pa, int precision, int polygonRing)
+static size_t
+assvg_inspected_size(LWGEOM_INSPECTED *insp, bool relative, int precision)
{
- int u;
- POINT2D pt, lpt;
- char x[MAX_DIGS_DOUBLE+3];
- char y[MAX_DIGS_DOUBLE+3];
+ int type = lwgeom_getType(insp->serialized_form[0]);
+ size_t size = 0;
+ LWPOINT *point;
+ LWLINE *line;
+ LWPOLY *poly;
- result += strlen(result);
+ switch(type) {
+ case POINTTYPE:
+ point=lwgeom_getpoint_inspected(insp, 0);
+ size = assvg_point_size(point, relative, precision);
+ lwpoint_release(point);
+ break;
+ case LINETYPE:
+ line=lwgeom_getline_inspected(insp, 0);
+ size = assvg_line_size(line, relative, precision);
+ lwline_release(line);
+ break;
+
+ case POLYGONTYPE:
+ poly=lwgeom_getpoly_inspected(insp, 0);
+ size = assvg_polygon_size(poly, relative, precision);
+ lwpoly_release(poly);
+
+ case MULTIPOINTTYPE:
+ size = assvg_multipoint_size(insp, relative, precision);
+ break;
+
+ case MULTILINETYPE:
+ size = assvg_multiline_size(insp, relative, precision);
+ break;
+
+ case MULTIPOLYGONTYPE:
+ size = assvg_multipolygon_size(insp, relative, precision);
+ break;
+
+ default: lwerror("ST_AsSVG: geometry not supported.");
+ }
+
+ return size;
+}
+
+
+static size_t
+pointArray_svg_rel(POINTARRAY *pa, char *output, bool close_ring, int precision)
+{
+ int i, end;
+ char *ptr;
+ char x[MAX_DIGS_DOUBLE+3];
+ char y[MAX_DIGS_DOUBLE+3];
+ POINT2D pt, lpt;
+
+ ptr = output;
+
+ if (close_ring) end = pa->npoints;
+ else end = pa->npoints - 1;
+
+ /* Starting point */
getPoint2d_p(pa, 0, &pt);
+ sprintf(x, "%.*f", precision, pt.x);
+ trim_trailing_zeros(x);
+ sprintf(y, "%.*f", precision, fabs(pt.y) ? pt.y * -1 : pt.y);
+ trim_trailing_zeros(y);
+ ptr += sprintf(ptr,"%s %s l", x, y);
- sprintf(x, "%.*f", precision, pt.x);
- trim_trailing_zeros(x);
- sprintf(y, "%.*f", precision, fabs(pt.y) > 0 ? (pt.y * -1) : pt.y);
- trim_trailing_zeros(y);
+ /* All the following ones */
+ for (i=1 ; i < end ; i++) {
+ lpt = pt;
+ getPoint2d_p(pa, i, &pt);
+ sprintf(x, "%.*f", precision, pt.x -lpt.x);
+ trim_trailing_zeros(x);
+ /* SVG Y axis is reversed, an no need to transform 0 into -0 */
+ sprintf(y, "%.*f", precision,
+ fabs(pt.y -lpt.y) ? (pt.y - lpt.y) * -1: (pt.y - lpt.y));
+ trim_trailing_zeros(y);
+ ptr += sprintf(ptr," %s %s", x, y);
+ }
- result += sprintf(result,"%s %s l", x, y);
+ return (ptr-output);
+}
- lpt = pt;
- for (u=1; u<pa->npoints; u++)
- {
- getPoint2d_p(pa, u, &pt);
- if(u == (pa->npoints - 1) && polygonRing)
- {
- /* close PATH with 'z' if last point equals first point */
- POINT2D firstPoint;
- getPoint2d_p(pa, 0, &firstPoint);
- if(pt.x == firstPoint.x && pt.y == firstPoint.y)
- {
- sprintf(result, " z");
- break;
- }
- }
+/*
+ * Returns maximum size of rendered pointarray in bytes.
+ */
+static size_t
+pointArray_svg_abs(POINTARRAY *pa, char *output, bool close_ring, int precision)
+{
+ int i, end;
+ char *ptr;
+ char x[MAX_DIGS_DOUBLE+3];
+ char y[MAX_DIGS_DOUBLE+3];
+ POINT2D pt;
- sprintf(x, "%.*f", precision, pt.x - lpt.x);
- trim_trailing_zeros(x);
- sprintf(y, "%.*f", precision, fabs(pt.y - lpt.y) > 0 ? ((pt.y - lpt.y) * -1) : (pt.y - lpt.y));
- trim_trailing_zeros(y);
- result+= sprintf(result," %s %s", x, y);
- lpt = pt;
- }
+ ptr = output;
+
+ if (close_ring) end = pa->npoints;
+ else end = pa->npoints - 1;
+
+ for (i=0 ; i < end ; i++) {
+ getPoint2d_p(pa, i, &pt);
+ sprintf(x, "%.*f", precision, pt.x);
+ trim_trailing_zeros(x);
+ /* SVG Y axis is reversed, an no need to transform 0 into -0 */
+ sprintf(y, "%.*f", precision, fabs(pt.y) ? pt.y * -1:pt.y);
+ trim_trailing_zeros(y);
+ if (i) ptr += sprintf(ptr, " ");
+ ptr += sprintf(ptr,"%s %s", x, y);
+ /* FIXME Could we really omit SVG L after M start point ? */
+ }
+
+ return (ptr-output);
}
-/**********************************************************************
- * $Log$
- * Revision 1.11 2006/01/09 15:55:55 strk
- * ISO C90 comments (finished in lwgeom/)
- *
- * Revision 1.10 2005/12/30 18:14:53 strk
- * Fixed all signedness warnings
- *
- * Revision 1.9 2005/11/18 10:16:21 strk
- * Removed casts on lwalloc return.
- * Used varlena macros when appropriate.
- *
- * Revision 1.8 2005/02/10 17:41:55 strk
- * Dropped getbox2d_internal().
- * Removed all castings of getPoint() output, which has been renamed
- * to getPoint_internal() and commented about danger of using it.
- * Changed SERIALIZED_FORM() macro to use VARDATA() macro.
- * All this changes are aimed at taking into account memory alignment
- * constraints which might be the cause of recent crash bug reports.
- *
- * Revision 1.7 2004/10/27 12:30:53 strk
- * AsSVG returns NULL on GEOMETRY COLLECTION input.
- *
- * Revision 1.6 2004/10/25 14:20:57 strk
- * Y axis reverse and relative path fixes from Olivier Courtin.
- *
- * Revision 1.5 2004/10/15 11:48:48 strk
- * Fixed a bug making asSVG return a spurious char at the end.
- *
- * Revision 1.4 2004/10/15 09:41:22 strk
- * changed precision semantic back to number of decimal digits
- *
- * Revision 1.3 2004/09/29 10:50:30 strk
- * Big layout change.
- * lwgeom.h is public API
- * liblwgeom.h is private header
- * lwgeom_pg.h is for PG-links
- * lw<type>.c contains type-specific functions
- *
- * Revision 1.2 2004/09/29 06:31:42 strk
- * Changed LWGEOM to PG_LWGEOM.
- * Changed LWGEOM_construct to PG_LWGEOM_construct.
- *
- * Revision 1.1 2004/09/13 13:32:01 strk
- * Added AsSVG().
- *
- **********************************************************************/
-
+/*
+ * Returns maximum size of rendered pointarray in bytes.
+ */
+static size_t
+pointArray_svg_size(POINTARRAY *pa, int precision)
+{
+ return (MAX_DIGS_DOUBLE + precision + sizeof(", "))
+ * 2 * pa->npoints + sizeof("l ");
+}
More information about the postgis-commits
mailing list