summaryrefslogtreecommitdiff
path: root/meme
diff options
context:
space:
mode:
authorWerner Almesberger <werner@almesberger.net>2015-03-14 11:10:08 (GMT)
committerWerner Almesberger <werner@almesberger.net>2015-03-14 11:10:08 (GMT)
commit5063fcc259c3f5c485ade53ea2a1b1882bec2d30 (patch)
tree579fa96ebac862b54651c8f0aad219c43ae0a4c4 /meme
parent7d70682e30d87204e1e441c7f6c7ecbd68fe1a07 (diff)
downloadmisc-5063fcc259c3f5c485ade53ea2a1b1882bec2d30.zip
misc-5063fcc259c3f5c485ade53ea2a1b1882bec2d30.tar.gz
misc-5063fcc259c3f5c485ade53ea2a1b1882bec2d30.tar.bz2
meme/: new option -s slice.gp for intersect the mesh with a plane (WIP)
Diffstat (limited to 'meme')
-rw-r--r--meme/Makefile2
-rw-r--r--meme/README16
-rw-r--r--meme/meme.c25
-rw-r--r--meme/slice.c194
-rw-r--r--meme/slice.h24
5 files changed, 257 insertions, 4 deletions
diff --git a/meme/Makefile b/meme/Makefile
index b0e377f..6032648 100644
--- a/meme/Makefile
+++ b/meme/Makefile
@@ -13,7 +13,7 @@
include Makefile.c-common
CFLAGS = -Wall -Wshadow -g -O9
-OBJS = meme.o stl.o mesh.o gui.o time.o plane.o text.o gaux.o overlay.o
+OBJS = meme.o stl.o mesh.o gui.o time.o plane.o text.o gaux.o overlay.o slice.o
CFLAGS += $(shell sdl-config --cflags)
LDLIBS = $(shell sdl-config --libs) -lSDL_gfx -lSDL_Pango -lm
diff --git a/meme/README b/meme/README
index 7d779a7..3e45022 100644
--- a/meme/README
+++ b/meme/README
@@ -5,6 +5,7 @@ Mesh measurement utility
Usage:
meme [-l logfile] [-o overlay.gp] <path-to-STL-file>
+meme -s slice.gp <path-to-STL-file>
Mouse
@@ -85,6 +86,21 @@ file containing the lines (in model coordinates) is specified with the
-o option. The O key toggle overlay display.
+Slicing
+-------
+
+An intersection of the mesh with a plane can be calculated using the -s
+option. The plane is described by the slice file containing points
+in the following format:
+
+x y z [zoff]
+
+If the zoff value is present, it is added to the z coordinate. This can
+be used to manually adjust coordinates obtained from the mesh.
+
+The output is a set of unconnected line segments, in Gnuplot format.
+
+
Workflow
--------
diff --git a/meme/meme.c b/meme/meme.c
index 411b7ca..0b1049d 100644
--- a/meme/meme.c
+++ b/meme/meme.c
@@ -19,6 +19,7 @@
#include "mesh.h"
#include "stl.h"
#include "overlay.h"
+#include "slice.h"
extern void gui(const char *logfile);
@@ -43,10 +44,18 @@ static unsigned count_edges(void)
}
+static void slice_out(double x, double y, double z, bool last)
+{
+ printf("%f %f %f\n%s", x, y, z, last ? "\n" : "");
+}
+
+
static void usage(const char *name)
{
- fprintf(stderr, "usage: %s [-l logfile] [-o overlap.gp] [file.stl]\n",
- name);
+ fprintf(stderr,
+"usage: %s [-l logfile] [-o overlap.gp] [file.stl]\n"
+" %s -s plane.gp [file.stl]\n",
+ name, name);
exit(1);
}
@@ -56,9 +65,10 @@ int main(int argc, char **argv)
int c;
const char *logfile = NULL;
const char *overlay = NULL;
+ const char *slice = NULL;
struct time t_load;
- while ((c = getopt(argc, argv, "l:o:")) != EOF)
+ while ((c = getopt(argc, argv, "l:o:s:")) != EOF)
switch (c) {
case 'l':
logfile = optarg;
@@ -66,6 +76,9 @@ int main(int argc, char **argv)
case 'o':
overlay = optarg;
break;
+ case 's':
+ slice = optarg;
+ break;
default:
usage(*argv);
}
@@ -88,6 +101,12 @@ int main(int argc, char **argv)
fprintf(stderr, "STL loaded in %.3f s\n", time_ms(&t_load)/1000.0);
fprintf(stderr, "%u edges\n", count_edges());
+ if (slice) {
+ slice_load(slice);
+ slice_run(slice_out, 0);
+ exit(1);
+ }
+
if (overlay)
overlay_load(overlay);
diff --git a/meme/slice.c b/meme/slice.c
new file mode 100644
index 0000000..8bfbd1e
--- /dev/null
+++ b/meme/slice.c
@@ -0,0 +1,194 @@
+/*
+ * slice.c - Intersect the mesh with a plane
+ *
+ * Written 2015 by Werner Almesberger
+ * Copyright 2015 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 <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "util.h"
+#include "mesh.h"
+#include "slice.h"
+
+
+#define EPSILON 1e-6
+
+
+struct point {
+ double x, y, z;
+ struct point *next;
+};
+
+static struct point *points = NULL;
+
+
+/* ----- Slicing plane ----------------------------------------------------- */
+
+
+static double z0, cx, cy; /* z = cx * x + cy * y + z0 */
+
+
+
+static void slice_plane(void)
+{
+ /* @@@ */
+ cx = cy = 0;
+ z0 = points->z;
+}
+
+
+/* ----- Slice the mesh ---------------------------------------------------- */
+
+
+static bool above(const struct vertex *v)
+{
+ return v->z > z0 + cx * v->x + cy * v->y;
+}
+
+
+static bool solve(const struct vertex *va, const struct vertex *vb, double *res)
+{
+ double dx, dy, dz;
+ double m, a;
+
+ dx = vb->x - va->x;
+ dy = vb->y - va->y;
+ dz = vb->z - va->z;
+
+ /*
+ * We solve this equation for t:
+ *
+ * x(t) = t * dx + va->x;
+ * y(t) = t * dy + va->y;
+ * z(t) = t * dz + va->z;
+ * cx * x(t) + cy * y(t) + z0 = z(t)
+ *
+ * Calculate m and a such that
+ * m * t + a = 0
+ */
+
+ m = cx * dx + cx * dy - dz;
+ a = cx * va->x + cy * va->y - va->z + z0;
+
+ if (fabs(m) < EPSILON)
+ return 0;
+
+ *res = -a / m;
+ 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)
+{
+ double dx, dy, dz;
+
+ dx = vb->x - va->x;
+ 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);
+}
+
+
+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);
+ }
+}
+
+
+void slice_run(void (*fn)(double x, double y, double z, bool last), bool needle)
+{
+ const struct facet *f;
+ bool a, b, c;
+
+ slice_plane();
+ for (f = facets; f; f = f->next) {
+ a = above(f->v[0]);
+ b = above(f->v[1]);
+ c = above(f->v[2]);
+ if (a && b && c)
+ continue;
+ if (!a && !b && !c)
+ continue;
+ if ((b && c) || (!b && !c))
+ segment(fn, f->v[0], f->v[1], f->v[2], needle);
+ if ((a && c) || (!a && !c))
+ segment(fn, f->v[1], f->v[0], f->v[2], needle);
+ if ((a && b) || (!a && !b))
+ segment(fn, f->v[2], f->v[0], f->v[1], needle);
+ }
+}
+
+
+/* ----- Points that define the slicing plane ------------------------------ */
+
+
+static void slice_load_file(FILE *file)
+{
+ struct point *p;
+ int lineno = 0;
+ char buf[1024];
+ int n;
+ double zoff;
+
+ p = alloc_type(struct point);
+ while (fgets(buf, sizeof(buf), file)) {
+ lineno++;
+ if (*buf == '#')
+ continue;
+ n = sscanf(buf, "%lf %lf %lf %lf\n",
+ &p->x, &p->y, &p->z, &zoff);
+ switch (n) {
+ case -1:
+ continue;
+ case 4:
+ p->z += zoff;
+ /* fall through */
+ case 3:
+ break;
+ default:
+ fprintf(stderr, "invalid data at line %d\n", lineno);
+ exit(1);
+ }
+
+ p->next = points;
+ points = p;
+ p = alloc_type(struct point);
+ }
+ free(p);
+}
+
+
+void slice_load(const char *name)
+{
+ FILE *file;
+
+ file = fopen(name, "r");
+ if (!file) {
+ perror(name);
+ exit(1);
+ }
+ slice_load_file(file);
+ fclose(file);
+}
diff --git a/meme/slice.h b/meme/slice.h
new file mode 100644
index 0000000..071fbf2
--- /dev/null
+++ b/meme/slice.h
@@ -0,0 +1,24 @@
+/*
+ * slice.h - Intersect the mesh with a plane
+ *
+ * Written 2015 by Werner Almesberger
+ * Copyright 2015 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.
+ */
+
+
+#ifndef SLICE_H
+#define SLICE_H
+
+#include <stdbool.h>
+
+
+void slice_run(void (*fn)(double x, double y, double z, bool last),
+ bool needle);
+void slice_load(const char *name);
+
+#endif /* !SLICE_H */