summaryrefslogtreecommitdiff
path: root/Build/source/libs/potrace/potrace-1.12/src/backend_dxf.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/potrace/potrace-1.12/src/backend_dxf.c')
-rw-r--r--Build/source/libs/potrace/potrace-1.12/src/backend_dxf.c278
1 files changed, 278 insertions, 0 deletions
diff --git a/Build/source/libs/potrace/potrace-1.12/src/backend_dxf.c b/Build/source/libs/potrace/potrace-1.12/src/backend_dxf.c
new file mode 100644
index 00000000000..938afde38be
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-1.12/src/backend_dxf.c
@@ -0,0 +1,278 @@
+/* Copyright (C) 2001-2015 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 DXF backend of Potrace. */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+
+#include "main.h"
+#include "backend_dxf.h"
+#include "potracelib.h"
+#include "lists.h"
+#include "auxiliary.h"
+#include "trans.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary linear algebra functions */
+
+/* subtract two vectors */
+static dpoint_t sub(dpoint_t v, dpoint_t w) {
+ dpoint_t r;
+
+ r.x = v.x - w.x;
+ r.y = v.y - w.y;
+ return r;
+}
+
+/* inner product */
+static double iprod(dpoint_t v, dpoint_t w) {
+ return v.x * w.x + v.y * w.y;
+}
+
+/* cross product */
+static double xprod(dpoint_t v, dpoint_t w) {
+ return v.x * w.y - v.y * w.x;
+}
+
+/* calculate the DXF polyline "bulge" value corresponding to the angle
+ between two vectors. In case of "infinity" return 0.0. */
+static double bulge(dpoint_t v, dpoint_t w) {
+ double v2, w2, vw, vxw, nvw;
+
+ v2 = iprod(v, v);
+ w2 = iprod(w, w);
+ vw = iprod(v, w);
+ vxw = xprod(v, w);
+ nvw = sqrt(v2 * w2);
+
+ if (vxw == 0.0) {
+ return 0.0;
+ }
+
+ return (nvw - vw) / vxw;
+}
+
+/* ---------------------------------------------------------------------- */
+/* DXF output synthesis */
+
+/* print with group code: the low-level DXF file format */
+static int ship(FILE *fout, int gc, const char *fmt, ...) {
+ va_list args;
+ int r;
+ int c;
+
+ r = fprintf(fout, "%3d\n", gc);
+ if (r < 0) {
+ return r;
+ }
+ c = r;
+ va_start(args, fmt);
+ r = vfprintf(fout, fmt, args);
+ va_end(args);
+ if (r < 0) {
+ return r;
+ }
+ c += r;
+ r = fprintf(fout, "\n");
+ if (r < 0) {
+ return r;
+ }
+ c += r;
+ return c;
+}
+
+/* output the start of a polyline */
+static void ship_polyline(FILE *fout, char *layer, int closed) {
+ ship(fout, 0, "POLYLINE");
+ ship(fout, 8, "%s", layer);
+ ship(fout, 66, "%d", 1);
+ ship(fout, 70, "%d", closed ? 1 : 0);
+}
+
+/* output a vertex */
+static void ship_vertex(FILE *fout, char *layer, dpoint_t v, double bulge) {
+ ship(fout, 0, "VERTEX");
+ ship(fout, 8, "%s", layer);
+ ship(fout, 10, "%f", v.x);
+ ship(fout, 20, "%f", v.y);
+ ship(fout, 42, "%f", bulge);
+}
+
+/* output the end of a polyline */
+static void ship_seqend(FILE *fout) {
+ ship(fout, 0, "SEQEND");
+}
+
+/* output a comment */
+static void ship_comment(FILE *fout, char *comment) {
+ ship(fout, 999, "%s", comment);
+}
+
+/* output the start of a section */
+static void ship_section(FILE *fout, char *name) {
+ ship(fout, 0, "SECTION");
+ ship(fout, 2, "%s", name);
+}
+
+static void ship_endsec(FILE *fout) {
+ ship(fout, 0, "ENDSEC");
+}
+
+static void ship_eof(FILE *fout) {
+ ship(fout, 0, "EOF");
+}
+
+/* ---------------------------------------------------------------------- */
+/* Simulated quadratic and bezier curves */
+
+/* Output vertices (with bulges) corresponding to a smooth pair of
+ circular arcs from A to B, tangent to AC at A and to CB at
+ B. Segments are meant to be concatenated, so don't output the final
+ vertex. */
+static void pseudo_quad(FILE *fout, char *layer, dpoint_t A, dpoint_t C, dpoint_t B) {
+ dpoint_t v, w;
+ double v2, w2, vw, vxw, nvw;
+ double a, b, c, y;
+ dpoint_t G;
+ double bulge1, bulge2;
+
+ v = sub(A, C);
+ w = sub(B, C);
+
+ v2 = iprod(v, v);
+ w2 = iprod(w, w);
+ vw = iprod(v, w);
+ vxw = xprod(v, w);
+ nvw = sqrt(v2 * w2);
+
+ a = v2 + 2*vw + w2;
+ b = v2 + 2*nvw + w2;
+ c = 4*nvw;
+ if (vxw == 0 || a == 0) {
+ goto degenerate;
+ }
+ /* assert: a,b,c >= 0, b*b - a*c >= 0, and 0 <= b - sqrt(b*b - a*c) <= a */
+ y = (b - sqrt(b*b - a*c)) / a;
+ G = interval(y, C, interval(0.5, A, B));
+
+ bulge1 = bulge(sub(A,G), v);
+ bulge2 = bulge(w, sub(B,G));
+
+ ship_vertex(fout, layer, A, -bulge1);
+ ship_vertex(fout, layer, G, -bulge2);
+ return;
+
+ degenerate:
+ ship_vertex(fout, layer, A, 0);
+
+ return;
+}
+
+/* produce a smooth from A to D, tangent to AB at A and to CD at D.
+ This is similar to a Bezier curve, except that our curve will be
+ made up of up to 4 circular arcs. This is particularly intended for
+ the case when AD and BC are parallel. Like arcs(), don't output the
+ final vertex. */
+static void pseudo_bezier(FILE *fout, char *layer, dpoint_t A, dpoint_t B, dpoint_t C, dpoint_t D) {
+ dpoint_t E = interval(0.75, A, B);
+ dpoint_t G = interval(0.75, D, C);
+ dpoint_t F = interval(0.5, E, G);
+
+ pseudo_quad(fout, layer, A, E, F);
+ pseudo_quad(fout, layer, F, G, D);
+ return;
+}
+
+/* ---------------------------------------------------------------------- */
+/* functions for converting a path to a DXF polyline */
+
+/* do one path. */
+static int dxf_path(FILE *fout, char *layer, potrace_curve_t *curve, trans_t t) {
+ int i;
+ dpoint_t *c, *c1;
+ int n = curve->n;
+
+ ship_polyline(fout, layer, 1);
+
+ for (i=0; i<n; i++) {
+ c = curve->c[i];
+ c1 = curve->c[mod(i-1,n)];
+ switch (curve->tag[i]) {
+ case POTRACE_CORNER:
+ ship_vertex(fout, layer, trans(c1[2], t), 0);
+ ship_vertex(fout, layer, trans(c[1], t), 0);
+ break;
+ case POTRACE_CURVETO:
+ pseudo_bezier(fout, layer, trans(c1[2], t), trans(c[0], t), trans(c[1], t), trans(c[2], t));
+ break;
+ }
+ }
+ ship_seqend(fout);
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Backend. */
+
+/* public interface for DXF */
+int page_dxf(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
+ potrace_path_t *p;
+ trans_t t;
+ char *layer = "0";
+
+ /* set up the coordinate transform (rotation) */
+ t.bb[0] = imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar;
+ t.bb[1] = imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar;
+ t.orig[0] = imginfo->trans.orig[0]+imginfo->lmar;
+ t.orig[1] = imginfo->trans.orig[1]+imginfo->bmar;
+ t.x[0] = imginfo->trans.x[0];
+ t.x[1] = imginfo->trans.x[1];
+ t.y[0] = imginfo->trans.y[0];
+ t.y[1] = imginfo->trans.y[1];
+
+ ship_comment(fout, "DXF data, created by "POTRACE" "VERSION", written by Peter Selinger 2001-2015");
+
+ /* header section */
+ ship_section(fout, "HEADER");
+
+ /* variables */
+ ship(fout, 9, "$ACADVER");
+ ship(fout, 1, "AC1006");
+ ship(fout, 9, "$EXTMIN");
+ ship(fout, 10, "%f", 0.0);
+ ship(fout, 20, "%f", 0.0);
+ ship(fout, 30, "%f", 0.0);
+ ship(fout, 9, "$EXTMAX");
+ ship(fout, 10, "%f", t.bb[0]);
+ ship(fout, 20, "%f", t.bb[1]);
+ ship(fout, 30, "%f", 0.0);
+
+ ship_endsec(fout);
+
+ /* entities section */
+ ship_section(fout, "ENTITIES");
+
+ /* write paths */
+ list_forall (p, plist) {
+ dxf_path(fout, layer, &p->curve, t);
+ }
+
+ ship_endsec(fout);
+ ship_eof(fout);
+
+ fflush(fout);
+ return 0;
+}
+