summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpacien2017-12-24 00:07:53 +0100
committerpacien2017-12-24 00:07:53 +0100
commitcdbae7a5e7515ba50ae21f15929a086fc40fcae3 (patch)
tree492c7451e559beb35b0680cd474adaa5a0d8f0d0
parent39cbe5d0d7db78f0d2808abea5562db84d03a07e (diff)
downloadmorpher-cdbae7a5e7515ba50ae21f15929a086fc40fcae3.tar.gz
Implement Delaunay propagation
Signed-off-by: pacien <pacien.trangirard@pacien.net>
-rw-r--r--include/morpher/quadrilateral.h11
-rw-r--r--include/morpher/trianglemap.h10
-rw-r--r--src/morpher/quadrilateral.c17
-rw-r--r--src/morpher/trianglemap.c7
-rw-r--r--test/morpher/quadrilateral.c26
5 files changed, 67 insertions, 4 deletions
diff --git a/include/morpher/quadrilateral.h b/include/morpher/quadrilateral.h
index c8cf3a1..8691263 100644
--- a/include/morpher/quadrilateral.h
+++ b/include/morpher/quadrilateral.h
@@ -36,4 +36,15 @@ void quadrilateral_flip_diagonal(TriangleMap *t1, TriangleMap *t2);
36 */ 36 */
37bool quadrilateral_is_delaunay(TriangleMap *t1, TriangleMap *t2); 37bool quadrilateral_is_delaunay(TriangleMap *t1, TriangleMap *t2);
38 38
39/**
40 * Function: quadrilateral_propagate_delaunay
41 * Ensures that the quadrilateral spawned by the given triangles fulfills the Delaunay criterion,
42 * flipping the diagonal if necessary and propagating the changes to the neighbouring triangles.
43 *
44 * Parameters:
45 * *start - the starting triangle
46 * *neighbor - a neighboring triangle
47 */
48void quadrilateral_propagate_delaunay(TriangleMap *start, TriangleMap *neighbor);
49
39#endif 50#endif
diff --git a/include/morpher/trianglemap.h b/include/morpher/trianglemap.h
index 05e7b87..0bb6a1d 100644
--- a/include/morpher/trianglemap.h
+++ b/include/morpher/trianglemap.h
@@ -106,6 +106,16 @@ void trianglemap_set_neighbors(TriangleMap *t, TriangleMap *n1, TriangleMap *n2,
106void trianglemap_replace_neighbor(TriangleMap *t, TriangleMap *old, TriangleMap *new); 106void trianglemap_replace_neighbor(TriangleMap *t, TriangleMap *old, TriangleMap *new);
107 107
108/** 108/**
109 * Function: trianglemap_foreach_neighbor
110 * Executes the given function for each existing (non-NULL) neighbour of the supplied triangle.
111 *
112 * Parameters:
113 * *t - the base triangle
114 * *f - the function
115 */
116void trianglemap_foreach_neighbor(TriangleMap *t, void (*f)(TriangleMap *current, TriangleMap *neighbor));
117
118/**
109 * Function: trianglemap_split 119 * Function: trianglemap_split
110 * Splits a triangle into three sub-triangles at the supplied center vertex, updating the surrounding triangles. 120 * Splits a triangle into three sub-triangles at the supplied center vertex, updating the surrounding triangles.
111 * The first triangle resulting from the split is returned, with the two others chained as linear neighbours. 121 * The first triangle resulting from the split is returned, with the two others chained as linear neighbours.
diff --git a/src/morpher/quadrilateral.c b/src/morpher/quadrilateral.c
index 9671116..af77f0f 100644
--- a/src/morpher/quadrilateral.c
+++ b/src/morpher/quadrilateral.c
@@ -1,5 +1,6 @@
1#include "morpher/quadrilateral.h" 1#include "morpher/quadrilateral.h"
2#include "common/geom.h" 2#include <stdlib.h>
3#include <assert.h>
3#include "morpher/matrix.h" 4#include "morpher/matrix.h"
4 5
5static inline IntVector p2(IntVector n) { 6static inline IntVector p2(IntVector n) {
@@ -47,12 +48,24 @@ static inline void rotate_neighbors(TriangleMap *t1, TriangleMap *t2, int e1, in
47} 48}
48 49
49void quadrilateral_flip_diagonal(TriangleMap *t1, TriangleMap *t2) { 50void quadrilateral_flip_diagonal(TriangleMap *t1, TriangleMap *t2) {
50 int e1 = trianglemap_find_common_edge(t1, t2), e2 = trianglemap_find_common_edge(t2, t1); 51 int e1, e2;
52 assert(t1 != NULL && t2 != NULL);
53 e1 = trianglemap_find_common_edge(t1, t2);
54 e2 = trianglemap_find_common_edge(t2, t1);
51 rotate_vertices(t1, t2, e1, e2); 55 rotate_vertices(t1, t2, e1, e2);
52 rotate_neighbors(t1, t2, e1, e2); 56 rotate_neighbors(t1, t2, e1, e2);
53} 57}
54 58
55bool quadrilateral_is_delaunay(TriangleMap *t1, TriangleMap *t2) { 59bool quadrilateral_is_delaunay(TriangleMap *t1, TriangleMap *t2) {
60 assert(t1 != NULL && t2 != NULL);
56 return not_in_circumcircle(t1, t2->vertices[(trianglemap_find_common_edge(t2, t1) + 2) % 3].origin) && 61 return not_in_circumcircle(t1, t2->vertices[(trianglemap_find_common_edge(t2, t1) + 2) % 3].origin) &&
57 not_in_circumcircle(t2, t1->vertices[(trianglemap_find_common_edge(t1, t2) + 2) % 3].origin); 62 not_in_circumcircle(t2, t1->vertices[(trianglemap_find_common_edge(t1, t2) + 2) % 3].origin);
58} 63}
64
65void quadrilateral_propagate_delaunay(TriangleMap *start, TriangleMap *neighbor) {
66 assert(start != NULL && neighbor != NULL);
67 if (!quadrilateral_is_delaunay(start, neighbor)) {
68 quadrilateral_flip_diagonal(start, neighbor);
69 trianglemap_foreach_neighbor(neighbor, quadrilateral_propagate_delaunay);
70 }
71}
diff --git a/src/morpher/trianglemap.c b/src/morpher/trianglemap.c
index 45f4ade..01b66c9 100644
--- a/src/morpher/trianglemap.c
+++ b/src/morpher/trianglemap.c
@@ -1,7 +1,6 @@
1#include "morpher/trianglemap.h" 1#include "morpher/trianglemap.h"
2#include <stdlib.h> 2#include <stdlib.h>
3#include <assert.h> 3#include <assert.h>
4#include "common/geom.h"
5#include "common/mem.h" 4#include "common/mem.h"
6 5
7TriangleMap *trianglemap_create(CartesianMapping v1, CartesianMapping v2, CartesianMapping v3) { 6TriangleMap *trianglemap_create(CartesianMapping v1, CartesianMapping v2, CartesianMapping v3) {
@@ -46,6 +45,12 @@ void trianglemap_replace_neighbor(TriangleMap *t, TriangleMap *old, TriangleMap
46 if (t != NULL) t->neighbors[trianglemap_find_common_edge(t, old)] = new; 45 if (t != NULL) t->neighbors[trianglemap_find_common_edge(t, old)] = new;
47} 46}
48 47
48void trianglemap_foreach_neighbor(TriangleMap *t, void (*f)(TriangleMap *, TriangleMap *)) {
49 int cursor;
50 assert(t != NULL);
51 for (cursor = 0; cursor < 3; ++cursor) if (t->neighbors[cursor] != NULL) f(t, t->neighbors[cursor]);
52}
53
49TriangleMap *trianglemap_split(TriangleMap *t, CartesianMapping v) { 54TriangleMap *trianglemap_split(TriangleMap *t, CartesianMapping v) {
50 assert(trianglemap_to(t, v.origin) == t); 55 assert(trianglemap_to(t, v.origin) == t);
51 56
diff --git a/test/morpher/quadrilateral.c b/test/morpher/quadrilateral.c
index 963d1d6..b278e2f 100644
--- a/test/morpher/quadrilateral.c
+++ b/test/morpher/quadrilateral.c
@@ -21,7 +21,6 @@ static inline bool vertices_equals(CartesianMapping maps[],
21 */ 21 */
22static void test_quadrilateral_flip_diagonal() { 22static void test_quadrilateral_flip_diagonal() {
23 CartesianMapping A = m(50, 0), B = m(0, 100), C = m(100, 100), D = m(0, 200), E = m(100, 200); 23 CartesianMapping A = m(50, 0), B = m(0, 100), C = m(100, 100), D = m(0, 200), E = m(100, 200);
24
25 TriangleMap *t = trianglemap_create(A, B, C); 24 TriangleMap *t = trianglemap_create(A, B, C);
26 TriangleMap *r = trianglemap_create(C, B, E); 25 TriangleMap *r = trianglemap_create(C, B, E);
27 TriangleMap *l = trianglemap_create(B, D, E); 26 TriangleMap *l = trianglemap_create(B, D, E);
@@ -54,9 +53,34 @@ static void test_quadrilateral_is_delaunay(CartesianMapping A, CartesianMapping
54 trianglemap_destroy(r); 53 trianglemap_destroy(r);
55} 54}
56 55
56static void test_quadrilateral_propagate_delaunay() {
57 CartesianMapping A = m(0, 0), B = m(0, 10), C = m(10, 10), D = m(10, 0), E = m(4, 6), F = m(8, 7);
58 TriangleMap *l = trianglemap_create(A, B, C);
59 TriangleMap *r = trianglemap_create(A, C, D);
60 trianglemap_set_neighbors(l, NULL, NULL, r, r);
61 trianglemap_set_neighbors(r, l, NULL, NULL, NULL);
62 trianglemap_split(l, E);
63 trianglemap_split(r, F);
64
65 trianglemap_foreach_neighbor(r, quadrilateral_propagate_delaunay);
66
67 {
68 TriangleMap *triangle;
69 int neighbor_index;
70 for (triangle = l; triangle != NULL; triangle = triangle->next)
71 for (neighbor_index = 0; neighbor_index < 3; ++neighbor_index)
72 if (triangle->neighbors[neighbor_index] != NULL)
73 assert(quadrilateral_is_delaunay(triangle, triangle->neighbors[neighbor_index]));
74 }
75
76 trianglemap_destroy(l);
77 trianglemap_destroy(r);
78}
79
57int main(int argc, char **argv) { 80int main(int argc, char **argv) {
58 test_quadrilateral_flip_diagonal(); 81 test_quadrilateral_flip_diagonal();
59 test_quadrilateral_is_delaunay(m(0, 0), m(0, 3), m(3, 3), m(2, 1), false); 82 test_quadrilateral_is_delaunay(m(0, 0), m(0, 3), m(3, 3), m(2, 1), false);
60 test_quadrilateral_is_delaunay(m(0, 0), m(0, 3), m(3, 3), m(4, -1), true); 83 test_quadrilateral_is_delaunay(m(0, 0), m(0, 3), m(3, 3), m(4, -1), true);
84 test_quadrilateral_propagate_delaunay();
61 return 0; 85 return 0;
62} 86}