diff options
Diffstat (limited to 'Build/source/libs/potrace/potrace-src/src/backend_geojson.c')
-rw-r--r-- | Build/source/libs/potrace/potrace-src/src/backend_geojson.c | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_geojson.c b/Build/source/libs/potrace/potrace-src/src/backend_geojson.c new file mode 100644 index 00000000000..8ac226b8969 --- /dev/null +++ b/Build/source/libs/potrace/potrace-src/src/backend_geojson.c @@ -0,0 +1,223 @@ +/* Copyright (C) 2001-2019 Peter Selinger. + This file is part of Potrace. It is free software and it is covered + by the GNU General Public License. See the file COPYING for details. */ + +/* The GeoJSON backend of Potrace. */ +/* Written 2012 by Christoph Hormann <chris_hormann@gmx.de> */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <math.h> + +#include "potracelib.h" +#include "curve.h" +#include "main.h" +#include "backend_geojson.h" +#include "lists.h" +#include "auxiliary.h" + +/* ---------------------------------------------------------------------- */ +/* auxiliary */ + +/* return a point on a 1-dimensional Bezier segment */ +static inline double bezier(double t, double x0, double x1, double x2, double x3) { + double s = 1-t; + return s*s*s*x0 + 3*(s*s*t)*x1 + 3*(t*t*s)*x2 + t*t*t*x3; +} + +static const char *format = "%f"; + +/* Convert a floating-point number to a string, using a pre-determined + format. The format must be previously set with set_format(). + Returns one of a small number of statically allocated strings. */ +static char *round_to_unit(double x) { + static int n = 0; + static char buf[4][100]; + + n++; + if (n >= 4) { + n = 0; + } + sprintf(buf[n], format, x); + return buf[n]; +} + +/* Select a print format for floating point numbers, appropriate for + the given scaling and info.unit. Note: the format must be so that + the resulting number fits into a buffer of size 100. */ +static void set_format(trans_t tr) { + double s; + int d; + static char buf[10]; + + s = min(fabs(tr.scalex), fabs(tr.scaley)); + if (info.unit != 0.0 && s != 0.0) { + d = (int)ceil(log(info.unit/s) / log(10)); + } else { + d = 0; + } + if (d <= 0) { + format = "%.0f"; + } else if (d <= 20) { + sprintf(buf, "%%.%df", d); + format = buf; + } else { + format = "%e"; + } +} + +/* ---------------------------------------------------------------------- */ +/* path-drawing auxiliary functions */ + +static dpoint_t cur; + +static void geojson_moveto(FILE *fout, dpoint_t p, trans_t tr) { + dpoint_t q; + + q = trans(p, tr); + + fprintf(fout, "[%s, %s]", round_to_unit(q.x), round_to_unit(q.y)); + + cur = q; +} + +static void geojson_lineto(FILE *fout, dpoint_t p, trans_t tr) { + dpoint_t q; + + q = trans(p, tr); + + fprintf(fout, ", [%s, %s]", round_to_unit(q.x), round_to_unit(q.y)); + + cur = q; +} + +static void geojson_curveto(FILE *fout, dpoint_t p1, dpoint_t p2, dpoint_t p3, trans_t tr) { + dpoint_t q1; + dpoint_t q2; + dpoint_t q3; + double step, t; + int i; + double x, y; + + q1 = trans(p1, tr); + q2 = trans(p2, tr); + q3 = trans(p3, tr); + + step = 1.0 / 8.0; + + for (i=0, t=step; i<8; i++, t+=step) { + x = bezier(t, cur.x, q1.x, q2.x, q3.x); + y = bezier(t, cur.y, q1.y, q2.y, q3.y); + + fprintf(fout, ", [%s, %s]", round_to_unit(x), round_to_unit(y)); + } + + cur = q3; +} + +/* ---------------------------------------------------------------------- */ +/* functions for converting a path to an SVG path element */ + +static int geojson_path(FILE *fout, potrace_curve_t *curve, trans_t tr) { + int i; + dpoint_t *c; + int m = curve->n; + + fprintf(fout, " ["); + + c = curve->c[m-1]; + geojson_moveto(fout, c[2], tr); + + for (i=0; i<m; i++) { + c = curve->c[i]; + switch (curve->tag[i]) { + case POTRACE_CORNER: + geojson_lineto(fout, c[1], tr); + geojson_lineto(fout, c[2], tr); + break; + case POTRACE_CURVETO: + geojson_curveto(fout, c[0], c[1], c[2], tr); + break; + } + } + + fprintf(fout, " ]"); + + return 0; +} + + +static void write_polygons(FILE *fout, potrace_path_t *tree, trans_t tr, int first) { + potrace_path_t *p, *q; + + for (p=tree; p; p=p->sibling) { + + if (!first) fprintf(fout, ",\n"); + + fprintf(fout, "{ \"type\": \"Feature\",\n"); + fprintf(fout, " \"properties\": { },\n"); + fprintf(fout, " \"geometry\": {\n"); + fprintf(fout, " \"type\": \"Polygon\",\n"); + fprintf(fout, " \"coordinates\": [\n"); + + geojson_path(fout, &p->curve, tr); + + for (q=p->childlist; q; q=q->sibling) { + fprintf(fout, ",\n"); + geojson_path(fout, &q->curve, tr); + } + + fprintf(fout, " ]\n"); + fprintf(fout, " }\n"); + fprintf(fout, "}"); + + for (q=p->childlist; q; q=q->sibling) { + write_polygons(fout, q->childlist, tr, 0); + } + + first = 0; + } +} + +/* ---------------------------------------------------------------------- */ +/* Backend. */ + +/* public interface for GeoJSON */ +int page_geojson(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) { + + trans_t tr; + + /* set up the coordinate transform (rotation) */ + tr.bb[0] = imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar; + tr.bb[1] = imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar; + tr.orig[0] = imginfo->trans.orig[0]+imginfo->lmar; + tr.orig[1] = imginfo->trans.orig[1]+imginfo->bmar; + tr.x[0] = imginfo->trans.x[0]; + tr.x[1] = imginfo->trans.x[1]; + tr.y[0] = imginfo->trans.y[0]; + tr.y[1] = imginfo->trans.y[1]; + + /* set the print format for floating point numbers */ + set_format(imginfo->trans); + + /* header */ + fprintf(fout, "{\n"); + fprintf(fout, "\"type\": \"FeatureCollection\",\n"); + fprintf(fout, "\"features\": [\n"); + + write_polygons(fout, plist, tr, 1); + + /* write footer */ + fprintf(fout, "\n]\n"); + fprintf(fout, "}\n"); + + fflush(fout); + + return 0; +} + |