From c202eda676591cf2ddf0a5736c9e98012e0d0d36 Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Fri, 29 Jul 2011 14:32:40 -0300 Subject: [PATCH] ptrude/: added (overly, this far) simple extruder --- ptrude/Makefile | 2 +- ptrude/extrude.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++ ptrude/mesh.fig | 65 +++++++++++++++++++++++++ ptrude/ptrude.c | 26 +++++++++- ptrude/tp | 10 ++++ ptrude/ts | 11 +++++ 6 files changed, 235 insertions(+), 2 deletions(-) create mode 100644 ptrude/extrude.c create mode 100644 ptrude/mesh.fig create mode 100644 ptrude/tp create mode 100644 ptrude/ts diff --git a/ptrude/Makefile b/ptrude/Makefile index 5e20068..f7dcf14 100644 --- a/ptrude/Makefile +++ b/ptrude/Makefile @@ -13,7 +13,7 @@ SHELL = /bin/bash MAIN = ptrude -OBJS = $(MAIN).o path.o +OBJS = $(MAIN).o path.o extrude.o CFLAGS = -Wall -g -Wshadow -Wmissing-prototypes \ -Wmissing-declarations -Wno-format-zero-length diff --git a/ptrude/extrude.c b/ptrude/extrude.c new file mode 100644 index 0000000..74d457e --- /dev/null +++ b/ptrude/extrude.c @@ -0,0 +1,123 @@ +/* + * extrude.c - Perform the extrusion + * + * Written 2011 by Werner Almesberger + * Copyright 2011 by 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. + */ + +/* + * Known bugs: + * + * - negative x coordinates in shape produce overlapping faces + * - the rounding is only accurate for x = 0. For x > 0, we need to add + * more points. Tricky. + */ + + +#include +#include +#include + +#include "path.h" +#include "extrude.h" + + +#define alloc_tn(t, n) ((t *) malloc(sizeof(t)*(n))) + + +static void slice(double x, double y, double nx, double ny, + const struct path *shape, struct point *p) +{ + const struct vertex *v; + + for (v = shape->vertices; v; v = v->next) { + p->x = x+nx*v->x; + p->y = y+ny*v->x; + p->z = v->y; + p++; + } +} + + +static void mesh(const struct point *a, const struct point *b, int n, + void (*face)(void *data, struct point a, struct point b, struct point c), + void *data) +{ + int i; + + for (i = 0; i != n-1; i++) { + face(data, a[i], b[i], a[i+1]); + face(data, a[i+1], b[i], b[i+1]); + } +} + + +void extrude(const struct path *path, const struct path *shape, + void (*face)(void *data, struct point a, struct point b, struct point c), + void *data) +{ + const struct vertex *v; /* current vertex (for iteration) */ + const struct vertex *a, *b, *c; /* previous, current, next vertex */ + struct point *prev, *this; /* previous and current slice */ + double nx, ny; /* 2D normals */ + double f; /* factor for normalization */ + double tx, ty; /* temporary 2D normals */ + int n = 0; /* number of vertices in shape */ + + if (!path->vertices || !path->vertices->next || !shape->vertices) + return; + + for (v = shape->vertices; v; v = v->next) + n++; + + prev = alloc_tn(struct point, n); + this = alloc_tn(struct point, n); + + a = path->vertices; + b = a->next; + nx = b->y-a->y; + ny = a->x-b->x; + f = hypot(nx, ny); + slice(a->x, a->y, nx/f, ny/f, shape, prev); + + for (v = path->vertices->next; v->next; v = v->next) { + b = v; + c = v->next; + + tx = b->y-a->y; + ty = a->x-b->x; + f = hypot(tx, ty); + nx = tx/f; + ny = ty/f; + + tx = c->y-b->y; + ty = b->x-c->x; + f = hypot(tx, ty); + nx += tx/f; + ny += ty/f; + + slice(b->x, b->y, nx/2, ny/2, shape, this); + mesh(prev, this, n, face, data); + + memcpy(prev, this, sizeof(*prev)*n); + + a = v; + } + + nx = v->y-a->y; + ny = a->x-v->x; + f = hypot(nx, ny); + + slice(v->x, v->y, nx/f, ny/f, shape, this); + mesh(prev, this, n, face, data); + + /* @@@ To do: close shape and close top and bottom */ + + free(prev); + free(this); +} diff --git a/ptrude/mesh.fig b/ptrude/mesh.fig new file mode 100644 index 0000000..81dbd41 --- /dev/null +++ b/ptrude/mesh.fig @@ -0,0 +1,65 @@ +#FIG 3.2 Produced by xfig version 3.2.5b +Landscape +Center +Metric +A4 +100.00 +Single +-2 +1200 2 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 2925 7200 4050 8325 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 2925 5400 4275 7200 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 2025 4500 4275 5400 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3420 4500 6930 4050 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 6075 3150 8325 2025 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 4275 5400 6975 5850 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 6975 5850 8100 4950 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 4275 7200 6750 6975 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 6975 4050 8280 3825 +2 1 0 3 1 7 50 -1 -1 0.000 0 0 -1 1 0 4 + 1 1 3.00 90.00 120.00 + 2700 8325 2925 7200 2925 5400 2025 4500 +2 1 0 2 1 7 50 -1 -1 0.000 0 0 7 0 0 4 + 4050 8325 4275 7200 4275 5400 3375 4500 +2 1 0 2 1 7 50 -1 -1 0.000 0 0 7 0 0 4 + 6750 6975 6975 5850 6975 4050 6075 3150 +2 1 0 2 1 7 50 -1 -1 0.000 0 0 7 0 0 4 + 8100 4950 8325 3825 8325 2025 7425 1125 +2 1 0 2 4 7 50 -1 -1 0.000 0 0 7 0 0 4 + 2025 4500 3375 4500 6075 3150 7425 1125 +2 1 0 2 4 7 50 -1 -1 0.000 0 0 7 0 0 4 + 2925 5400 4275 5400 6975 4050 8325 2025 +2 1 0 3 4 7 50 -1 -1 0.000 0 0 -1 1 0 4 + 1 1 3.00 90.00 120.00 + 2925 7200 4275 7200 6975 5850 8325 3825 +2 1 0 2 4 7 50 -1 -1 0.000 0 0 7 0 0 4 + 2709 8343 4059 8343 6759 6993 8109 4968 +2 1 0 2 4 7 52 -1 -1 0.000 0 0 -1 0 0 2 + 3195 6975 3015 7155 +2 1 0 2 1 7 52 -1 -1 0.000 0 0 -1 0 0 2 + 2520 7200 2790 7200 +2 1 0 2 1 7 52 -1 -1 0.000 0 0 -1 0 0 2 + 2250 8505 2565 8370 +3 2 0 2 0 7 50 -1 -1 0.000 0 1 0 3 + 0 0 2.00 90.00 120.00 + 4680 6705 5580 6075 4545 5805 + 0.000 -1.000 0.000 +3 2 0 2 0 7 50 -1 -1 0.000 0 1 0 3 + 0 0 2.00 90.00 120.00 + 5265 5265 6570 5445 6705 4545 + 0.000 -1.000 0.000 +4 2 1 50 -1 18 18 0.0000 4 270 870 2835 6480 Shape\001 +4 1 4 50 -1 18 18 0.0000 4 210 615 3690 7515 Path\001 +4 1 4 50 -1 19 15 0.0000 4 240 375 3330 6930 tag\001 +4 1 1 50 -1 19 15 0.0000 4 240 375 2295 7245 tag\001 +4 1 1 50 -1 14 15 0.0000 4 135 750 1845 8640 start\001 +4 1 1 50 -1 18 12 0.0000 4 195 1365 2205 8865 (or unique tag)\001 diff --git a/ptrude/ptrude.c b/ptrude/ptrude.c index 4520083..7043f36 100644 --- a/ptrude/ptrude.c +++ b/ptrude/ptrude.c @@ -17,6 +17,7 @@ #include #include "path.h" +#include "extrude.h" #include "ptrude.h" @@ -50,6 +51,29 @@ static void close_file(FILE *file) } +static void do_face(void *data, struct point a, struct point b, struct point c) +{ + FILE *file = data; + + fprintf(file, "facet normal 0 0 0\n"); + fprintf(file, " outer loop\n"); + fprintf(file, " vertex %f %f %f\n", a.x, a.y, a.z); + fprintf(file, " vertex %f %f %f\n", b.x, b.y, b.z); + fprintf(file, " vertex %f %f %f\n", c.x, c.y, c.z); + fprintf(file, " endloop\nendfacet\n"); +} + + +static void do_extrude(const struct path *path, const struct path *shape) +{ + FILE *file = stdout; + + fprintf(file, "solid ptrude\n"); + extrude(path, shape, do_face, file); + fprintf(file, "endsolid ptrude\n"); +} + + static void usage(const char *name) { fprintf(stderr, @@ -106,7 +130,7 @@ int main(int argc, char **argv) */ path = round_path(path, r, sqrt(d)); shape = round_path(shape, r, sqrt(d)); - /* ... now all that's missing is the extrusion :-) */ + do_extrude(path, shape); } else { shape = round_path(shape, r, d); save_path(stdout, shape); diff --git a/ptrude/tp b/ptrude/tp new file mode 100644 index 0000000..84afe06 --- /dev/null +++ b/ptrude/tp @@ -0,0 +1,10 @@ +# test path +-100 0 +100 0 +200 100 +200 200 +100 300 +0 300 +-100 200 +-100 100 +0 100 diff --git a/ptrude/ts b/ptrude/ts new file mode 100644 index 0000000..487c359 --- /dev/null +++ b/ptrude/ts @@ -0,0 +1,11 @@ +# test shape +0 100 +0 0 +50 0 +50 50 +100 150 +100 200 +50 250 +50 300 +0 300 +0 250