summaryrefslogtreecommitdiff
path: root/meme
diff options
context:
space:
mode:
authorWerner Almesberger <werner@almesberger.net>2015-03-14 19:35:58 (GMT)
committerWerner Almesberger <werner@almesberger.net>2015-03-14 19:35:58 (GMT)
commit6b7491bd5298dd31c09c63bf08adbc1f7013345d (patch)
tree436ff9e7866b8da6f95db6108e2d9284f8c99a3a /meme
parent21d686b4c66f725ddf76e9e5fa6a416e7028fe77 (diff)
downloadmisc-6b7491bd5298dd31c09c63bf08adbc1f7013345d.zip
misc-6b7491bd5298dd31c09c63bf08adbc1f7013345d.tar.gz
misc-6b7491bd5298dd31c09c63bf08adbc1f7013345d.tar.bz2
meme/: new option -n to select outline calculation based on needle shape
Diffstat (limited to 'meme')
-rw-r--r--meme/README8
-rw-r--r--meme/meme.c11
-rw-r--r--meme/needle.fig79
-rw-r--r--meme/slice.c80
4 files changed, 165 insertions, 13 deletions
diff --git a/meme/README b/meme/README
index e5380bf..b5ae293 100644
--- a/meme/README
+++ b/meme/README
@@ -5,7 +5,7 @@ Mesh measurement utility
Usage:
meme [-l logfile] [-o overlay.gp ...] <path-to-STL-file>
-meme -s slice.gp <path-to-STL-file>
+meme -s slice.gp [-n] <path-to-STL-file>
Mouse
@@ -107,6 +107,12 @@ be used to manually adjust coordinates obtained from the mesh.
The output is a set of unconnected line segments, in Gnuplot format.
+Two algorithms are available for interpolating between measurement
+points: by default, the plane is simply intersected with a the mesh
+edges connecting two points. If the -n option is given, the real
+position of the edge is calculated considering the shape of the
+scanning needle. This is illustrated in needle.fig
+
Workflow
--------
diff --git a/meme/meme.c b/meme/meme.c
index aab8736..4480f3f 100644
--- a/meme/meme.c
+++ b/meme/meme.c
@@ -11,6 +11,7 @@
*/
+#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
@@ -55,7 +56,7 @@ static void usage(const char *name)
{
fprintf(stderr,
"usage: %s [-l logfile] [-o overlay.gp ...] [file.stl]\n"
-" %s -s plane.gp [file.stl]\n",
+" %s -s plane.gp [-n] [file.stl]\n",
name, name);
exit(1);
}
@@ -66,15 +67,19 @@ int main(int argc, char **argv)
int c;
const char *logfile = NULL;
const char *slice = NULL;
+ bool needle = 0;
const struct overlay *overlays[N_OVERLAYS];
unsigned n_overlays = 0;
struct time t_load;
- while ((c = getopt(argc, argv, "l:o:s:")) != EOF)
+ while ((c = getopt(argc, argv, "l:no:s:")) != EOF)
switch (c) {
case 'l':
logfile = optarg;
break;
+ case 'n':
+ needle = 1;
+ break;
case 'o':
if (n_overlays == N_OVERLAYS) {
fprintf(stderr, "too many overlays\n");
@@ -110,7 +115,7 @@ int main(int argc, char **argv)
if (slice) {
slice_load(slice);
- slice_run(slice_out, 0);
+ slice_run(slice_out, needle);
exit(1);
}
diff --git a/meme/needle.fig b/meme/needle.fig
new file mode 100644
index 0000000..41e5c25
--- /dev/null
+++ b/meme/needle.fig
@@ -0,0 +1,79 @@
+#FIG 3.2 Produced by xfig version 3.2.5c
+Landscape
+Center
+Metric
+A4
+100.00
+Single
+-2
+1200 2
+5 1 0 2 0 7 50 -1 -1 0.000 0 1 0 0 7200.000 5265.000 6300 5265 7200 6165 8100 5265
+5 1 0 2 0 7 50 -1 -1 0.000 0 1 0 0 8865.000 5355.000 8820 5355 8865 5400 8910 5355
+1 3 0 2 0 7 50 -1 -1 6.000 1 0.0000 9450 4275 64 64 9450 4275 9495 4320
+1 3 0 2 0 7 50 -1 -1 6.000 1 0.0000 9135 5760 64 64 9135 5760 9180 5805
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+ 5310 5760 5490 5940
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+ 5310 5940 5490 5760
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+ 7110 6255 7290 6075
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+ 7110 6075 7290 6255
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+ 8100 5265 8190 4005
+2 1 1 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
+ 6345 5265 8055 5265
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+ 6300 5265 6210 4005
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
+ 8775 4050 8775 4725 8820 5355
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 0 0 3
+ 8955 4050 8955 4725 8910 5355
+2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
+ 8955 5400 9450 5400
+2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
+ 9000 4725 9450 4725
+2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
+ 8910 5445 9000 5625
+2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
+ 9000 4140 9225 4140
+2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
+ 9360 4185 9540 4365
+2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
+ 9045 5670 9225 5850
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
+ 1 1 2.00 60.00 60.00
+ 1 1 2.00 60.00 60.00
+ 9360 4725 9360 5400
+2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
+ 7200 6300 7200 6975
+2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
+ 5400 6300 5400 6975
+2 3 0 0 0 7 60 -1 17 0.000 0 0 -1 0 0 5
+ 4500 5850 6525 5850 6525 7200 4770 7200 4500 5850
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
+ 1 1 2.00 60.00 60.00
+ 1 1 2.00 60.00 60.00
+ 6525 6525 7200 6525
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
+ 1 1 2.00 60.00 60.00
+ 1 1 2.00 60.00 60.00
+ 5400 6885 7200 6885
+2 1 0 2 0 7 50 -1 -1 6.000 0 0 -1 0 0 2
+ 6885 6165 6075 6165
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
+ 1 1 2.00 60.00 60.00
+ 1 1 2.00 60.00 60.00
+ 6165 6165 6165 5850
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 -1 1 1 2
+ 1 1 2.00 60.00 60.00
+ 1 1 2.00 60.00 60.00
+ 7200 5265 7830 5895
+4 0 0 50 -1 22 12 0.0000 4 135 480 9270 5805 80 um\001
+4 0 0 50 -1 22 12 0.0000 4 135 435 9585 4320 1 mm\001
+4 0 0 50 -1 22 12 0.0000 4 135 435 9450 5130 7 mm\001
+4 2 0 50 -1 22 12 0.0000 4 105 75 6075 6075 z\001
+4 1 0 50 -1 22 12 0.0000 4 105 90 6840 6705 e\001
+4 1 0 50 -1 22 12 0.0000 4 135 105 6300 7110 d\001
+4 0 0 50 -1 22 12 0.0000 4 180 1365 7650 6750 e^2 + (r-z)^2 = r^2\001
+4 1 0 50 -1 22 12 0.0000 4 105 60 7650 5625 r\001
diff --git a/meme/slice.c b/meme/slice.c
index 9bf2ce5..2ce8657 100644
--- a/meme/slice.c
+++ b/meme/slice.c
@@ -21,7 +21,8 @@
#include "slice.h"
-#define EPSILON 1e-6
+#define EPSILON 1e-6
+#define MAX_WARN 100
struct point {
@@ -38,7 +39,6 @@ static struct point *points = NULL;
static double z0, cx, cy; /* z = cx * x + cy * y + z0 */
-
static void slice_plane(void)
{
/* @@@ */
@@ -87,9 +87,9 @@ static bool solve(const struct vertex *va, const struct vertex *vb, double *res)
return 1;
}
+
static void calc(void (*fn)(double x, double y, double z, bool last),
- const struct vertex *va, const struct vertex *vb, double t,
- bool needle, bool last)
+ const struct vertex *va, const struct vertex *vb, double t, bool last)
{
double dx, dy, dz;
@@ -97,22 +97,84 @@ static void calc(void (*fn)(double x, double y, double z, bool last),
dy = vb->y - va->y;
dz = vb->z - va->z;
- /* @@@ needle correction */
-
fn((va->x + t * dx) / 1000, (va->y + t * dy) / 1000,
(va->z + t * dz) / 1000, last);
}
+/*
+ * Known bug: we don't take into account horizontal needle deflection.
+ * E.g., when slightly beyond a vertical drop, the needle may bend as
+ * it plunges, thus reporting a lower height than a perfectly rigid
+ * needle would.
+ *
+ * If this happens, e may become larger than d and we simply go back to
+ * using the last point before the edge.
+ */
+
+
+#define NEEDLE_TIP_R 40 /* 40 um */
+#define NEEDLE_SIDE 14 /* dy = 14 * dx */
+
+
+static void step(void (*fn)(double x, double y, double z, bool last),
+ const struct vertex *va, const struct vertex *vb, bool last)
+{
+ static unsigned warnings = 0;
+ double dx, dy, dz;
+ double d, e, t;
+
+ if (va->z > vb->z) {
+ step(fn, vb, va, last);
+ return;
+ }
+
+ dx = vb->x - va->x;
+ dy = vb->y - va->y;
+ dz = vb->z - va->z;
+
+ d = hypot(dx, dy);
+
+ if (dz < NEEDLE_TIP_R) {
+ /*
+ * From:
+ * e^2 + (r - z)^2 = r^2
+ */
+ e = sqrt(2 * NEEDLE_TIP_R * dz - dz * dz);
+ } else {
+ e = (dz - NEEDLE_TIP_R) / NEEDLE_SIDE + NEEDLE_TIP_R;
+ }
+
+ if (e > d) {
+ if (warnings < MAX_WARN) {
+ fprintf(stderr, "e > d: %f, %f; dz = %f\n", e, d, dz);
+ } else if (warnings == MAX_WARN) {
+ fprintf(stderr, "...\n");
+ warnings++;
+ }
+ fn(vb->x / 1000.0, vb->y / 1000.0, vb->z / 1000.0, last);
+ } else {
+ t = fabs(d) < EPSILON ? 0 : e / d;
+ fn((va->x + t * dx) / 1000, (va->y + t * dy) / 1000,
+ vb->z / 1000, last);
+ }
+}
+
+
static void segment(void (*fn)(double x, double y, double z, bool last),
const struct vertex *va, const struct vertex *vb, const struct vertex *vc,
bool needle)
{
double tb, tc;
- if (solve(va, vb, &tb) && solve(va, vc, &tc)) {
- calc(fn, va, vb, tb, needle, 0);
- calc(fn, va, vc, tc, needle, 1);
+ if (needle) {
+ step(fn, va, vb, 0);
+ step(fn, va, vc, 1);
+ } else {
+ if (solve(va, vb, &tb) && solve(va, vc, &tc)) {
+ calc(fn, va, vb, tb, 0);
+ calc(fn, va, vc, tc, 1);
+ }
}
}