[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