return (ptr-output);
}
+/*
+ * Print an ordinate value using at most the given number of decimal digits
+ *
+ * The actual number of printed decimal digits may be less than the
+ * requested ones if out of significant digits.
+ *
+ * The function will not write more than maxsize bytes, including the
+ * terminating NULL. Returns the number of bytes that would have been
+ * written if there was enough space (excluding terminating NULL).
+ * So a return of ``bufsize'' or more means that the string was
+ * truncated and misses a terminating NULL.
+ *
+ * TODO: export ?
+ *
+ */
+static int
+lwprint_double(double d, int maxdd, char *buf, size_t bufsize)
+{
+ double ad = fabs(d);
+ int ndd = ad < 1 ? 0 : floor(log10(ad))+1; /* non-decimal digits */
+ if (fabs(d) < OUT_MAX_DOUBLE)
+ {
+ if ( maxdd > (OUT_MAX_DOUBLE_PRECISION - ndd) ) maxdd -= ndd;
+ return snprintf(buf, bufsize, "%.*f", maxdd, d);
+ }
+ else
+ {
+ return snprintf(buf, bufsize, "%g", d);
+ }
+}
+
+
static size_t
pointArray_to_geojson(POINTARRAY *pa, char *output, int precision)
{
int i;
char *ptr;
- char x[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
- char y[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
- char z[OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION+1];
+#define BUFSIZE OUT_MAX_DIGS_DOUBLE+OUT_MAX_DOUBLE_PRECISION
+ char x[BUFSIZE+1];
+ char y[BUFSIZE+1];
+ char z[BUFSIZE+1];
assert ( precision <= OUT_MAX_DOUBLE_PRECISION );
+ /* Ensure a terminating NULL at the end of buffers
+ * so that we don't need to check for truncation
+ * inprint_double */
+ x[BUFSIZE] = '\0';
+ y[BUFSIZE] = '\0';
+ z[BUFSIZE] = '\0';
+
ptr = output;
+ /* TODO: rewrite this loop to be simpler and possibly quicker */
if (!FLAGS_GET_Z(pa->flags))
{
for (i=0; i<pa->npoints; i++)
POINT2D pt;
getPoint2d_p(pa, i, &pt);
- if (fabs(pt.x) < OUT_MAX_DOUBLE)
- sprintf(x, "%.*f", precision, pt.x);
- else
- sprintf(x, "%g", pt.x);
- trim_trailing_zeros(x);
-
- if (fabs(pt.y) < OUT_MAX_DOUBLE)
- sprintf(y, "%.*f", precision, pt.y);
- else
- sprintf(y, "%g", pt.y);
- trim_trailing_zeros(y);
+ lwprint_double(pt.x, precision, x, BUFSIZE);
+ trim_trailing_zeros(x);
+ lwprint_double(pt.y, precision, y, BUFSIZE);
+ trim_trailing_zeros(y);
if ( i ) ptr += sprintf(ptr, ",");
ptr += sprintf(ptr, "[%s,%s]", x, y);
POINT4D pt;
getPoint4d_p(pa, i, &pt);
- if (fabs(pt.x) < OUT_MAX_DOUBLE)
- sprintf(x, "%.*f", precision, pt.x);
- else
- sprintf(x, "%g", pt.x);
- trim_trailing_zeros(x);
-
- if (fabs(pt.y) < OUT_MAX_DOUBLE)
- sprintf(y, "%.*f", precision, pt.y);
- else
- sprintf(y, "%g", pt.y);
- trim_trailing_zeros(y);
-
- if (fabs(pt.z) < OUT_MAX_DOUBLE)
- sprintf(z, "%.*f", precision, pt.z);
- else
- sprintf(z, "%g", pt.z);
- trim_trailing_zeros(z);
+ lwprint_double(pt.x, precision, x, BUFSIZE);
+ trim_trailing_zeros(x);
+ lwprint_double(pt.y, precision, y, BUFSIZE);
+ trim_trailing_zeros(y);
+ lwprint_double(pt.z, precision, z, BUFSIZE);
+ trim_trailing_zeros(z);
if ( i ) ptr += sprintf(ptr, ",");
ptr += sprintf(ptr, "[%s,%s,%s]", x, y, z);