--- Begin Message ---
Author: werner
Date: 2010-01-04 18:09:19 +0100 (Mon, 04 Jan 2010)
New Revision: 5778
Added:
developers/werner/cncmap/align/
developers/werner/cncmap/align/Makefile
developers/werner/cncmap/align/align.c
Log:
Added "align" tool to map model coordinates to the workpiece.
Added: developers/werner/cncmap/align/Makefile
===================================================================
--- developers/werner/cncmap/align/Makefile (rev 0)
+++ developers/werner/cncmap/align/Makefile 2010-01-04 17:09:19 UTC (rev
5778)
@@ -0,0 +1,25 @@
+#
+# align/Makefile - Build the model aligner
+#
+# Written 2008-2010 by Werner Almesberger
+# Copyright 2008-2010 Werner Almesberger
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+
+
+MAIN=align
+
+OBJS=align.o
+
+CFLAGS = -g -Wall -Wshadow
+LDFLAGS = -lm
+
+$(MAIN): $(OBJS)
+# $(CC) $(LDFLAGS) -o $(MAIN) $(OBJS)
+
+clean:
+ rm -f $(OBJS)
Added: developers/werner/cncmap/align/align.c
===================================================================
--- developers/werner/cncmap/align/align.c (rev 0)
+++ developers/werner/cncmap/align/align.c 2010-01-04 17:09:19 UTC (rev
5778)
@@ -0,0 +1,224 @@
+/*
+ * align.c - Align the model with the workpiece
+ *
+ * Written 2009, 2010 by Werner Almesberger
+ * Copyright 2009, 2010 Werner Almesberger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+
+/* ----- reorient ---------------------------------------------------------- */
+
+
+/*
+ * For alignment, we prefer a different normalization than the one "rect" gives
+ * us. We use:
+ * - lower left corner, followed by
+ * - rightmost low corner, followed by
+ * - topmost left corner
+ *
+ * The heuristics below only work if the workpiece is more or less parallel to
+ * the axes and not extremely elongated.
+ */
+
+static int reorient_pick(double xm, double ym, double x, double y)
+{
+ if (x < xm && y < ym)
+ return 0;
+ if (x > xm && y < ym)
+ return 1;
+ if (x < xm && y > ym)
+ return 2;
+ return -1;
+}
+
+
+static int reorient(double q[6], double xm, double ym, double x, double y)
+{
+ int pick;
+
+ pick = reorient_pick(xm, ym, x, y);
+ if (pick < 0)
+ return 0;
+ q[pick*2] = x;
+ q[pick*2+1] = y;
+ return 1 << pick;
+}
+
+
+static void make_matrix(double m[3][2], double angle, double ox, double oy,
+ int ref, double p[9])
+{
+ double xm, ym;
+ double q[6];
+ int r1, r2, r3, r4;
+ double x, y, a;
+
+ xm = (p[2]+p[4])/2;
+ ym = (p[3]+p[5])/2;
+ r1 = reorient(q, xm, ym, p[0], p[1]);
+ r2 = reorient(q, xm, ym, p[2], p[3]);
+ r3 = reorient(q, xm, ym, p[4], p[5]);
+ r4 = reorient(q, xm, ym, p[2]+p[4]-p[0], p[3]+p[5]-p[1]);
+
+ if ((r1 | r2 | r3 | r4) != 7 ||
+ (r1 & r2) || (r1 & r3) || (r1 & r4) ||
+ (r2 & r3) || (r2 & r4) ||
+ (r3 & r4)) {
+ fprintf(stderr, "workpiece orientation is too weird\n");
+ exit(1);
+ }
+
+ x = q[0]+((ref-1) % 3)*(q[2]-q[0])/2+((ref-1)/3)*(q[4]-q[0])/2;
+ y = q[1]+((ref-1) % 3)*(q[3]-q[1])/2+((ref-1)/3)*(q[5]-q[1])/2;
+
+ a = atan2(q[3]-q[1], q[2]-q[0]);
+ a += angle/180.0*M_PI;
+
+ /*
+ * x' = m[0][0]+x*m[1][0]+y*m[2][0]
+ * y' = m[0][1]+x*m[1][1]+y*m[2][1]
+ */
+
+ m[1][0] = cos(a);
+ m[2][0] = -sin(a);
+ m[1][1] = sin(a);
+ m[2][1] = cos(a);
+ m[0][0] = x-ox*m[1][0]-oy*m[2][0];
+ m[0][1] = y-ox*m[1][1]-oy*m[2][1];
+}
+
+
+/*
+ * Returns the lenght of the projection of OP on OA, normalized to the range
+ * 0 if P = O and 1 if P = A.
+ */
+
+static double project(double px, double py, double ox, double oy,
+ double ax, double ay)
+{
+ ax -= ox;
+ ay -= oy;
+ return ((px-ox)*ax+(py-oy)*ay)/(ax*ax+ay*ay);
+}
+
+
+static void process_file(FILE *file, double m[3][2], double p[6])
+{
+ static int warn = 10;
+ int lineno = 0;
+ char buf[1024];
+ double x, y, z;
+ double rx, ry, f1, f2;
+ int n;
+
+ while (fgets(buf, sizeof(buf), file)) {
+ lineno++;
+ n = sscanf(buf, "%lf %lf %lf\n", &x, &y, &z);
+ switch (n) {
+ case -1:
+ printf("\n");
+ continue;
+ case 2:
+ case 3:
+ rx = m[0][0]+x*m[1][0]+y*m[2][0];
+ ry = m[0][1]+x*m[1][1]+y*m[2][1];
+ f1 = project(rx, ry, p[0], p[1], p[2], p[3]);
+ f2 = project(rx, ry, p[0], p[1], p[4], p[5]);
+ if (f1 < 0 || f1 > 1 || f2 < 0 || f2 > 1) {
+ if (warn) {
+ fprintf(stderr,
+ "warning: point %f %f (from %f %f)"
+ " is outside the workpiece\n",
+ rx, ry, x, y);
+ warn--;
+ } else {
+ fprintf(stderr, "(more warnings)\n");
+ }
+ }
+ printf("%f %f", rx, ry);
+ if (n == 2)
+ printf("\n");
+ else
+ printf(" %f\n", z);
+ break;
+ default:
+ fprintf(stderr, "invalid data at line %d\n", lineno);
+ exit(1);
+ }
+ }
+}
+
+
+static void usage(const char *name)
+{
+ fprintf(stderr,
+"usage: %s angle [ox oy] reference x0 y0 ax ay bx by\n\n"
+" angle counter-clockwise rotation to apply to input\n"
+" before aligning, in degrees\n"
+" ox oy origin of model, in mm (default: 0 0) 7 8 9\n"
+" reference reference point for alignment, as shown here: 4 5 6\n"
+" 1 is lower left corner, 5 is center, etc. 1 2 3\n"
+" x0 y0 ax ay bx by\n"
+" normalized rectangle, as provided by \"rect\"\n",
+ name);
+ exit(1);
+}
+
+
+int main(int argc, const char **argv)
+{
+ double angle, ox, oy, p[6];
+ char *end;
+ int ref, i;
+ double m[3][2];
+
+ switch (argc) {
+ case 9:
+ ox = 0;
+ oy = 0;
+ break;
+ case 11:
+ ox = strtod(argv[2], &end);
+ if (*end)
+ usage(*argv);
+ oy = strtod(argv[3], &end);
+ if (*end)
+ usage(*argv);
+ break;
+ default:
+ usage(*argv);
+ }
+
+ angle = strtod(argv[1], &end);
+ if (*end)
+ usage(*argv);
+
+ for (i = 0; i != 6; i++) {
+ p[i] = strtod(argv[argc-6+i], &end);
+ if (*end)
+ usage(*argv);
+ }
+
+ if (!argv[argc-7][0] || argv[argc-7][1])
+ usage(*argv);
+ ref = atoi(argv[argc-7]);
+ if (ref < 1 || ref > 9)
+ usage(*argv);
+
+ make_matrix(m, angle, ox, oy, ref, p);
+ process_file(stdin, m, p);
+
+ return 0;
+}
+
+//*** range check
--- End Message ---