/* * slice.c - Generate slices * * Written 2015 by Werner Almesberger * Copyright 2015 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. */ #include #include #include #include "util.h" #include "stl.h" #include "slice.h" struct line { float ax, ay; float bx, by; float cz; struct line *next; }; struct z { float z; bool present; struct line *lines; }; static GTree *tree; static inline bool eq(float a, float b) { return fabsf(a - b) < 1e-6; } static struct z *get_z(float z) { struct z *base; base = g_tree_lookup(tree, &z); if (base) return base; base = alloc_type(struct z); base->z = z; base->present = 0; base->lines = NULL; g_tree_insert(tree, &base->z, base); return base; } static void mark_z(float z) { struct z *base; base = get_z(z); base->present = 1; } static void add(const struct v *a, const struct v *b, const struct v *c) { float cross; struct z *z; struct line *line; if (eq(a->x, b->x) && eq(a->y, b->y)) { fprintf(stderr, "zero point\n"); return; } if (c->z < a->z) return; cross = (b->x - a->x) * (c->y - a->y) - (b->y - a->y) * (c->x - a->x); if (!eq(cross, 0)) { fprintf(stderr, "inclined facet\n\t%f %f %f\n\t%f %f %f\n\t%f %f %f\n", a->x, a->y, a->z, b->x, b->y, b->z, c->x, c->y, c->z); exit(1); } z = get_z(a->z); line = alloc_type(struct line); line->ax = a->x; line->ay = a->y; line->bx = b->x; line->by = b->y; line->cz = c->z; line->next = z->lines; z->lines = line; } void slice(struct v f[3]) { bool ab = eq(f[0].z, f[1].z); bool bc = eq(f[1].z, f[2].z); bool ac = eq(f[0].z, f[2].z); if (ab && bc) mark_z(f[0].z); else if (ab) add(f + 0, f + 1, f + 2); else if (bc) add(f + 1, f + 2, f + 0); else if (ac) add(f + 0, f + 2, f + 1); } /* ----- Dumping ----------------------------------------------------------- */ static gboolean dump_layer(gpointer key, gpointer value, gpointer data) { const struct z *z0 = data; const struct z *z1 = value; const struct line *line; if (z0->z > z1->z) return 0; if (!z1->present) return 0; for (line = z0->lines; line; line = line->next) if (line->cz >= z1->z) printf("%f %f %f\n%f %f %f\n\n\n", line->ax, line->ay, z1->z, line->bx, line->by, z1->z); return 0; } static gboolean dump_range(gpointer key, gpointer value, gpointer data) { const struct z *z = value; if (z->present) g_tree_foreach(tree, dump_layer, value); return 0; } void slice_dump(void) { g_tree_foreach(tree, dump_range, NULL); } /* ----- Initialization ---------------------------------------------------- */ static gint comp(gconstpointer a, gconstpointer b) { const float *za = a; const float *zb = b; return eq(*za, *zb) ? 0 : *za < *zb ? -1 : 1; } void slice_init(void) { tree = g_tree_new(comp); }