diff options
author | pacien | 2017-12-24 00:07:53 +0100 |
---|---|---|
committer | pacien | 2017-12-24 00:07:53 +0100 |
commit | cdbae7a5e7515ba50ae21f15929a086fc40fcae3 (patch) | |
tree | 492c7451e559beb35b0680cd474adaa5a0d8f0d0 | |
parent | 39cbe5d0d7db78f0d2808abea5562db84d03a07e (diff) | |
download | morpher-cdbae7a5e7515ba50ae21f15929a086fc40fcae3.tar.gz |
Implement Delaunay propagation
Signed-off-by: pacien <pacien.trangirard@pacien.net>
-rw-r--r-- | include/morpher/quadrilateral.h | 11 | ||||
-rw-r--r-- | include/morpher/trianglemap.h | 10 | ||||
-rw-r--r-- | src/morpher/quadrilateral.c | 17 | ||||
-rw-r--r-- | src/morpher/trianglemap.c | 7 | ||||
-rw-r--r-- | test/morpher/quadrilateral.c | 26 |
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 | */ |
37 | bool quadrilateral_is_delaunay(TriangleMap *t1, TriangleMap *t2); | 37 | bool 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 | */ | ||
48 | void 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, | |||
106 | void trianglemap_replace_neighbor(TriangleMap *t, TriangleMap *old, TriangleMap *new); | 106 | void 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 | */ | ||
116 | void 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 | ||
5 | static inline IntVector p2(IntVector n) { | 6 | static 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 | ||
49 | void quadrilateral_flip_diagonal(TriangleMap *t1, TriangleMap *t2) { | 50 | void 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 | ||
55 | bool quadrilateral_is_delaunay(TriangleMap *t1, TriangleMap *t2) { | 59 | bool 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 | |||
65 | void 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 | ||
7 | TriangleMap *trianglemap_create(CartesianMapping v1, CartesianMapping v2, CartesianMapping v3) { | 6 | TriangleMap *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 | ||
48 | void 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 | |||
49 | TriangleMap *trianglemap_split(TriangleMap *t, CartesianMapping v) { | 54 | TriangleMap *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 | */ |
22 | static void test_quadrilateral_flip_diagonal() { | 22 | static 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 | ||
56 | static 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 | |||
57 | int main(int argc, char **argv) { | 80 | int 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 | } |