[postgis-tickets] r14455 - #2232, avoid accumulated error in SVG rounding
Paul Ramsey
pramsey at cleverelephant.ca
Mon Nov 30 08:30:58 PST 2015
Author: pramsey
Date: 2015-11-30 08:30:57 -0800 (Mon, 30 Nov 2015)
New Revision: 14455
Modified:
branches/2.1/NEWS
branches/2.1/liblwgeom/lwout_svg.c
Log:
#2232, avoid accumulated error in SVG rounding
Modified: branches/2.1/NEWS
===================================================================
--- branches/2.1/NEWS 2015-11-30 16:30:47 UTC (rev 14454)
+++ branches/2.1/NEWS 2015-11-30 16:30:57 UTC (rev 14455)
@@ -3,6 +3,7 @@
* Bug Fixes *
+ - #2232, avoid accumulated error in SVG rounding
- #3198, ST_AddEdgeModFace docs report wrong side of new face
- #3196, do not let DropTopology drop non-topology schemes
- #3222, Fix uninitialized stddev in stats computation
Modified: branches/2.1/liblwgeom/lwout_svg.c
===================================================================
--- branches/2.1/liblwgeom/lwout_svg.c 2015-11-30 16:30:47 UTC (rev 14454)
+++ branches/2.1/liblwgeom/lwout_svg.c 2015-11-30 16:30:57 UTC (rev 14455)
@@ -548,54 +548,78 @@
{
int i, end;
char *ptr;
- char x[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
- char y[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
- POINT2D pt, lpt;
+ char sx[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
+ char sy[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
+ const POINT2D *pt;
+ double f = 1.0;
+ double dx, dy, x, y, accum_x, accum_y;
+
ptr = output;
+ if (precision >= 0)
+ {
+ f = pow(10, precision);
+ }
+
if (close_ring) end = pa->npoints;
else end = pa->npoints - 1;
/* Starting point */
- getPoint2d_p(pa, 0, &pt);
+ pt = getPoint2d_cp(pa, 0);
- if (fabs(pt.x) < OUT_MAX_DOUBLE)
- sprintf(x, "%.*f", precision, pt.x);
+ x = round(pt->x*f)/f;
+ y = round(pt->y*f)/f;
+
+ if (fabs(x) < OUT_MAX_DOUBLE)
+ sprintf(sx, "%.*f", precision, x);
else
- sprintf(x, "%g", pt.x);
- trim_trailing_zeros(x);
+ sprintf(sx, "%g", x);
+ trim_trailing_zeros(sx);
- if (fabs(pt.y) < OUT_MAX_DOUBLE)
- sprintf(y, "%.*f", precision, fabs(pt.y) ? pt.y * -1 : pt.y);
+ if (fabs(y) < OUT_MAX_DOUBLE)
+ sprintf(sy, "%.*f", precision, fabs(y) ? y * -1 : y);
else
- sprintf(y, "%g", fabs(pt.y) ? pt.y * -1 : pt.y);
- trim_trailing_zeros(y);
+ sprintf(sy, "%g", fabs(y) ? y * -1 : y);
+ trim_trailing_zeros(sy);
- ptr += sprintf(ptr,"%s %s l", x, y);
+ ptr += sprintf(ptr,"%s %s l", sx, sy);
+
+ /* accum */
+ accum_x = x;
+ accum_y = y;
/* All the following ones */
for (i=1 ; i < end ; i++)
{
- lpt = pt;
+ // lpt = pt;
- getPoint2d_p(pa, i, &pt);
- if (fabs(pt.x -lpt.x) < OUT_MAX_DOUBLE)
- sprintf(x, "%.*f", precision, pt.x -lpt.x);
+ pt = getPoint2d_cp(pa, i);
+
+ x = round(pt->x*f)/f;
+ y = round(pt->y*f)/f;
+ dx = x - accum_x;
+ dy = y - accum_y;
+
+ if (fabs(dx) < OUT_MAX_DOUBLE)
+ sprintf(sx, "%.*f", precision, dx);
else
- sprintf(x, "%g", pt.x -lpt.x);
- trim_trailing_zeros(x);
+ sprintf(sx, "%g", dx);
+ trim_trailing_zeros(sx);
/* SVG Y axis is reversed, an no need to transform 0 into -0 */
- if (fabs(pt.y -lpt.y) < OUT_MAX_DOUBLE)
- sprintf(y, "%.*f", precision,
- fabs(pt.y -lpt.y) ? (pt.y - lpt.y) * -1: (pt.y - lpt.y));
+ if (fabs(dy) < OUT_MAX_DOUBLE)
+ sprintf(sy, "%.*f", precision,
+ fabs(dy) ? dy * -1: dy);
else
- sprintf(y, "%g",
- fabs(pt.y -lpt.y) ? (pt.y - lpt.y) * -1: (pt.y - lpt.y));
- trim_trailing_zeros(y);
+ sprintf(sy, "%g",
+ fabs(dy) ? dy * -1: dy);
+ trim_trailing_zeros(sy);
+
+ accum_x += dx;
+ accum_y += dy;
- ptr += sprintf(ptr," %s %s", x, y);
+ ptr += sprintf(ptr," %s %s", sx, sy);
}
return (ptr-output);
More information about the postgis-tickets
mailing list