[postgis-commits] svn - r2744 - in trunk: . doc lwgeom
postgis-commits at postgis.refractions.net
postgis-commits at postgis.refractions.net
Fri Mar 28 13:03:42 PDT 2008
Author: pramsey
Date: 2008-03-28 13:03:42 -0700 (Fri, 28 Mar 2008)
New Revision: 2744
Modified:
trunk/ChangeLog
trunk/doc/postgis.xml
trunk/lwgeom/lwgeom_svg.c
Log:
Added SVN support patch from Dr. Marco Hugentobler, as described in http://postgis.refractions.net/pipermail/postgis-devel/2008-February/002883.html
Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog 2008-03-28 19:25:16 UTC (rev 2743)
+++ trunk/ChangeLog 2008-03-28 20:03:42 UTC (rev 2744)
@@ -1,5 +1,11 @@
2008-03-28 Paul Ramsey <pramsey at cleverelephant.ca>
+ * doc/postgis.xml, lwgeom/lwgeom_svn.c,
+ Added patch from Marco Hugentobler to enhance SVG
+ support. 2008-February/002883.html
+
+2008-03-28 Paul Ramsey <pramsey at cleverelephant.ca>
+
* Makefile.config.in, configure.in, lwgeom/Makefile,
lwgeom/lwpostgis.sql.in, lwgeom/lwgeom_geos_c.c
Changed GEOS version checking to use geos-config, and
Modified: trunk/doc/postgis.xml
===================================================================
--- trunk/doc/postgis.xml 2008-03-28 19:25:16 UTC (rev 2743)
+++ trunk/doc/postgis.xml 2008-03-28 20:03:42 UTC (rev 2744)
@@ -4406,12 +4406,13 @@
<term>ST_AsSVG(geometry, [rel], [precision])</term>
<listitem>
- <para>Return the geometry as an SVG path data. Use 1 as second
- argument to have the path data implemented in terms of relative
- moves, the default (or 0) uses absolute moves. Third argument
- may be used to reduce the maximum number of decimal digits used
- in output (defaults to 15). Point geometries will be rendered as
- cx/cy when 'rel' arg is 0, x/y when 'rel' is 1.</para>
+ <para>Return the geometry as SVG path data. Use 1 as second argument to have the
+ path data implemented in terms of relative moves, the default (or 0) uses
+ absolute moves. Third argument may be used to reduce the maximum number of
+ decimal digits used in output (defaults to 15). Point geometries will be
+ rendered as cx/cy when 'rel' arg is 0, x/y when 'rel' is 1. Multipoint
+ geometries are delimited by commas (","), GeometryCollection geometries are
+ delimited by semicolons (";").</para>
</listitem>
</varlistentry>
Modified: trunk/lwgeom/lwgeom_svg.c
===================================================================
--- trunk/lwgeom/lwgeom_svg.c 2008-03-28 19:25:16 UTC (rev 2743)
+++ trunk/lwgeom/lwgeom_svg.c 2008-03-28 20:03:42 UTC (rev 2744)
@@ -25,8 +25,8 @@
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);
-void print_svg_path_rel(char *result, POINTARRAY *pa, 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);
#define SHOW_DIGS_DOUBLE 15
#define MAX_DOUBLE_PRECISION 15
@@ -82,19 +82,56 @@
char *
geometry_to_svg(PG_LWGEOM *geometry, int svgrel, int precision)
{
- char *result;
+ char *result = NULL;
LWGEOM_INSPECTED *inspected;
int t,u;
POINT2D pt;
+ int npts;
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)
{
- return NULL;
+ LWCOLLECTION* theCollection = lwcollection_deserialize(SERIALIZED_FORM(geometry));
+
+ PG_LWGEOM* theGeom;
+ char* geomSvg;
+ int i;
+
+ 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;
+ }
+
+ if(i == 0)
+ {
+ result = geomSvg;
+ }
+ else
+ {
+ result = repalloc(result, size);
+ strcat(result, ";");
+ strncat(result, geomSvg, strlen(geomSvg));
+ pfree(geomSvg);
+ }
+ pfree(theGeom);
+ }
+ return result;
}
result = palloc(size);
@@ -137,17 +174,20 @@
size +=(MAX_DIGS_DOUBLE*3+5)*line->points->npoints+12+3;
result = repalloc(result, size);
+ if(t)
+ {
+ strcat(result, " ");
+ }
+
/* start path with moveto */
strcat(result, "M ");
if (svgrel == 1)
print_svg_path_rel(result, line->points,
- precision);
+ precision, 0);
else
print_svg_path_abs( result, line->points,
- precision);
-
- strcat(result, " ");
+ precision, 0);
}
if (lwgeom_getType(subgeom[0]) == POLYGONTYPE)
{
@@ -158,22 +198,30 @@
npts += poly->rings[u]->npoints;
size += (MAX_DIGS_DOUBLE*3+3) * npts +
- 5 * poly->nrings;
+ 5 * poly->nrings + 1;
result = repalloc(result, size);
+ if(t)
+ {
+ strcat(result, " ");
+ }
+
for (u=0; u<poly->nrings; u++) /*for each ring */
{
+ if(u)
+ {
+ strcat(result," "); /*Blank separator from previous ring*/
+ }
+
strcat(result,"M "); /*begin ring */
if (svgrel == 1)
print_svg_path_rel(result,
poly->rings[u],
- precision);
+ precision, 1);
else
print_svg_path_abs(result,
poly->rings[u],
- precision);
-
- strcat(result," "); /*end ring */
+ precision, 1);
}
}
}
@@ -192,7 +240,7 @@
sprintf(x, "%.*f", precision, pt->x);
trim_trailing_zeros(x);
- sprintf(y, "%.*f", precision, pt->y * -1);
+ sprintf(y, "%.*f", precision, fabs(pt->y) > 0 ? (pt->y * -1) : pt->y);
trim_trailing_zeros(y);
sprintf(temp, "x=\"%s\" y=\"%s\"", x, y);
@@ -211,7 +259,7 @@
sprintf(x, "%.*f", precision, pt->x);
trim_trailing_zeros(x);
- sprintf(y, "%.*f", precision, pt->y * -1);
+ sprintf(y, "%.*f", precision, fabs(pt->y) > 0 ? (pt->y * -1) : pt->y);
trim_trailing_zeros(y);
sprintf(temp, "cx=\"%s\" cy=\"%s\"", x, y);
@@ -220,7 +268,7 @@
void
-print_svg_path_abs(char *result, POINTARRAY *pa, int precision)
+print_svg_path_abs(char *result, POINTARRAY *pa, int precision, int polygonRing)
{
int u;
POINT2D pt;
@@ -231,14 +279,28 @@
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;
+ }
+ }
+
if (u != 0)
{
result[0] = ' ';
result++;
}
+
sprintf(x, "%.*f", precision, pt.x);
trim_trailing_zeros(x);
- sprintf(y, "%.*f", precision, pt.y * -1);
+ 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);
}
@@ -246,7 +308,7 @@
void
-print_svg_path_rel(char *result, POINTARRAY *pa, int precision)
+print_svg_path_rel(char *result, POINTARRAY *pa, int precision, int polygonRing)
{
int u;
POINT2D pt, lpt;
@@ -259,7 +321,7 @@
sprintf(x, "%.*f", precision, pt.x);
trim_trailing_zeros(x);
- sprintf(y, "%.*f", precision, pt.y * -1);
+ sprintf(y, "%.*f", precision, fabs(pt.y) > 0 ? (pt.y * -1) : pt.y);
trim_trailing_zeros(y);
result += sprintf(result,"%s %s l", x, y);
@@ -267,13 +329,26 @@
lpt = pt;
for (u=1; u<pa->npoints; u++)
{
- getPoint2d_p(pa, u, &pt);
- sprintf(x, "%.*f", precision, pt.x - lpt.x);
- trim_trailing_zeros(x);
- sprintf(y, "%.*f", precision, (pt.y - lpt.y) * -1);
- trim_trailing_zeros(y);
- result+= sprintf(result," %s %s", x, y);
- lpt = pt;
+ 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;
+ }
+ }
+
+ 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;
}
}
More information about the postgis-commits
mailing list