diff options
author | pacien | 2017-12-22 01:57:03 +0100 |
---|---|---|
committer | pacien | 2017-12-22 01:57:25 +0100 |
commit | 553dc4a5b272a1828940e72a07b1c9a7210be464 (patch) | |
tree | 0dfaf1b2e3229e064258e4dc5c117a1250f40f87 | |
parent | a767c658cb603de9ec9f0577627b9b32cbf82b2b (diff) | |
download | morpher-553dc4a5b272a1828940e72a07b1c9a7210be464.tar.gz |
Add triangle map and quadrilateral representation and common operations
Signed-off-by: pacien <pacien.trangirard@pacien.net>
-rw-r--r-- | include/morpher/quadrilateral.h | 39 | ||||
-rw-r--r-- | include/morpher/trianglemap.h | 123 | ||||
-rw-r--r-- | src/morpher/quadrilateral.c | 58 | ||||
-rw-r--r-- | src/morpher/trianglemap.c | 64 | ||||
-rw-r--r-- | test/morpher/quadrilateral.c | 71 | ||||
-rw-r--r-- | test/morpher/trianglemap.c | 71 |
6 files changed, 426 insertions, 0 deletions
diff --git a/include/morpher/quadrilateral.h b/include/morpher/quadrilateral.h new file mode 100644 index 0000000..c8cf3a1 --- /dev/null +++ b/include/morpher/quadrilateral.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #ifndef UPEM_MORPHING_QUADRILATERAL | ||
2 | #define UPEM_MORPHING_QUADRILATERAL | ||
3 | |||
4 | /** | ||
5 | * File: quadrilateral.h | ||
6 | * Operations on quadrilaterals formed by adjacent triangles pairs. | ||
7 | */ | ||
8 | |||
9 | #include <stdbool.h> | ||
10 | #include "common/geom.h" | ||
11 | #include "morpher/trianglemap.h" | ||
12 | |||
13 | /** | ||
14 | * Function: quadrilateral_flip_diagonal | ||
15 | * Flips the diagonal of a quadrilateral formed by two triangles sharing a common edge, | ||
16 | * using a positive rotation-like transform inverting both references. | ||
17 | * This transforms keeps the positive orientation of the vertices. | ||
18 | * Pointers to surrounding triangles are updated accordingly. | ||
19 | * | ||
20 | * Parameters: | ||
21 | * *t1 - the first triangle | ||
22 | * *t2 - the second triangle | ||
23 | */ | ||
24 | void quadrilateral_flip_diagonal(TriangleMap *t1, TriangleMap *t2); | ||
25 | |||
26 | /** | ||
27 | * Function: quadrilateral_is_delaunay | ||
28 | * Tells whether the quadrilateral formed by the two supplied adjacent triangle forms a Delaunay triangulation. | ||
29 | * | ||
30 | * Parameters: | ||
31 | * *t1 - first triangle | ||
32 | * *t2 - second triangle adjacent to the first one | ||
33 | * | ||
34 | * Returns: | ||
35 | * T(t1 and t2 are a Delaunay triangulation in the quadrilateral formed by the twos) | ||
36 | */ | ||
37 | bool quadrilateral_is_delaunay(TriangleMap *t1, TriangleMap *t2); | ||
38 | |||
39 | #endif | ||
diff --git a/include/morpher/trianglemap.h b/include/morpher/trianglemap.h new file mode 100644 index 0000000..05e7b87 --- /dev/null +++ b/include/morpher/trianglemap.h | |||
@@ -0,0 +1,123 @@ | |||
1 | #ifndef UPEM_MORPHING_TRIANGLEMAP | ||
2 | #define UPEM_MORPHING_TRIANGLEMAP | ||
3 | |||
4 | /** | ||
5 | * File: trianglemap.h | ||
6 | * Represents a triangle map in a triangulation, in a plane oriented left to right and top to bottom. | ||
7 | */ | ||
8 | |||
9 | #include <stdbool.h> | ||
10 | #include "common/geom.h" | ||
11 | |||
12 | /** | ||
13 | * Struct: TriangleMap | ||
14 | * Represents a triangle mapping. | ||
15 | * | ||
16 | * Fields: | ||
17 | * vertices[] - array of vertices | ||
18 | * *neighbors[] - array of neighboring triangles ordered by the edges spawned by the vertices | ||
19 | * *next - pointer to another triangle for linear browsing, or NULL | ||
20 | */ | ||
21 | typedef struct _TriangleMap { | ||
22 | CartesianMapping vertices[3]; | ||
23 | struct _TriangleMap *neighbors[3]; | ||
24 | struct _TriangleMap *next; | ||
25 | } TriangleMap; | ||
26 | |||
27 | /** | ||
28 | * Function: trianglemap_create | ||
29 | * Creates a TriangleMap, instantiating it on the heap. | ||
30 | * | ||
31 | * Parameters: | ||
32 | * vertex1 - first vertex | ||
33 | * vertex2 - second vertex | ||
34 | * vertex3 - third vertex | ||
35 | * | ||
36 | * Returns: | ||
37 | * A pointer to the newly created triangle | ||
38 | */ | ||
39 | TriangleMap *trianglemap_create(CartesianMapping v1, CartesianMapping v2, CartesianMapping v3); | ||
40 | |||
41 | /** | ||
42 | * Function: trianglemap_destroy | ||
43 | * Destroys a triangle, freeing its dynamically allocated resources. | ||
44 | * Also returns the next triangle for convenience. | ||
45 | * Does not update surrounding triangles. | ||
46 | * | ||
47 | * Parameters: | ||
48 | * *t - pointer to the triangle to destroy | ||
49 | * | ||
50 | * Returns: | ||
51 | * A pointer to the next linear triangle | ||
52 | */ | ||
53 | TriangleMap *trianglemap_destroy(TriangleMap *t); | ||
54 | |||
55 | /** | ||
56 | * Function: trianglemap_to | ||
57 | * Returns a pointer to the current or the closest adjacent neighbour TriangleMap | ||
58 | * minimizing the distance to the targeted position. | ||
59 | * | ||
60 | * Parameters: | ||
61 | * *t - the origin triangle | ||
62 | * v - the target position vector | ||
63 | * | ||
64 | * Returns: | ||
65 | * A pointer to the current or an immediate neighbour TriangleMap | ||
66 | */ | ||
67 | TriangleMap *trianglemap_to(TriangleMap *t, CartesianVector v); | ||
68 | |||
69 | /** | ||
70 | * Function: trianglemap_find_common_edge | ||
71 | * Finds the index of the commonly shared edge in the neighbourhood of t. | ||
72 | * | ||
73 | * Parameters: | ||
74 | * *t - the base triangle | ||
75 | * *neighbor - the neighbour to search for | ||
76 | * | ||
77 | * Returns: | ||
78 | * The index of the common neighbour in the listing of t. | ||
79 | */ | ||
80 | int trianglemap_find_common_edge(TriangleMap *t, TriangleMap *neighbor); | ||
81 | |||
82 | /** | ||
83 | * Function: trianglemap_set_neighbors | ||
84 | * Updates a triangle neighbors. | ||
85 | * Vertices must be given in a positively oriented (trigonometric) order. | ||
86 | * Neighbours must be given in the same order as the vertices. | ||
87 | * | ||
88 | * Parameters: | ||
89 | * *t - the triangle to modify | ||
90 | * *n1 - first neighbour | ||
91 | * *n2 - second neighbour | ||
92 | * *n3 - third neighbour | ||
93 | * *next - linear neighbour | ||
94 | */ | ||
95 | void trianglemap_set_neighbors(TriangleMap *t, TriangleMap *n1, TriangleMap *n2, TriangleMap *n3, TriangleMap *next); | ||
96 | |||
97 | /** | ||
98 | * Function: triangle_replace_neighbor | ||
99 | * Substitutes a given neighbour in a neighbourhood. | ||
100 | * | ||
101 | * Parameters: | ||
102 | * *t - the base triangle | ||
103 | * *old - the neighbour to replace | ||
104 | * *new - the new neighbour | ||
105 | */ | ||
106 | void trianglemap_replace_neighbor(TriangleMap *t, TriangleMap *old, TriangleMap *new); | ||
107 | |||
108 | /** | ||
109 | * Function: trianglemap_split | ||
110 | * 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. | ||
112 | * Those generated triangles each have one of the original surrounding neighbour as first element in their listings. | ||
113 | * | ||
114 | * Parameters: | ||
115 | * *t - the triangle to split | ||
116 | * v - the new vertex to add | ||
117 | * | ||
118 | * Returns: | ||
119 | * The first generated TriangleMap | ||
120 | */ | ||
121 | TriangleMap *trianglemap_split(TriangleMap *t, CartesianMapping v); | ||
122 | |||
123 | #endif | ||
diff --git a/src/morpher/quadrilateral.c b/src/morpher/quadrilateral.c new file mode 100644 index 0000000..b9e740b --- /dev/null +++ b/src/morpher/quadrilateral.c | |||
@@ -0,0 +1,58 @@ | |||
1 | #include "morpher/quadrilateral.h" | ||
2 | #include "common/geom.h" | ||
3 | #include "morpher/matrix.h" | ||
4 | |||
5 | static inline IntVector p2(IntVector n) { | ||
6 | return n * n; | ||
7 | } | ||
8 | |||
9 | static inline bool in_circumcircle(TriangleMap *t, CartesianVector v) { | ||
10 | CartesianVector a = t->vertices[0].origin, b = t->vertices[1].origin, c = t->vertices[2].origin; | ||
11 | IntVector v2 = p2(v.x) + p2(v.y); | ||
12 | return matrix_int_det3(a.x - v.x, a.y - v.y, p2(a.x) + p2(a.y) - v2, | ||
13 | b.x - v.x, b.y - v.y, p2(b.x) + p2(b.y) - v2, | ||
14 | c.x - v.x, c.y - v.y, p2(c.x) + p2(c.y) - v2) > 0; | ||
15 | } | ||
16 | |||
17 | static inline void rotate_vertices(TriangleMap *t1, TriangleMap *t2, int e1, int e2) { | ||
18 | CartesianMapping quad[] = { | ||
19 | t1->vertices[(e1 + 1) % 3], | ||
20 | t1->vertices[(e1 + 2) % 3], | ||
21 | t2->vertices[(e2 + 1) % 3], | ||
22 | t2->vertices[(e2 + 2) % 3] | ||
23 | }; | ||
24 | |||
25 | t1->vertices[(e1 + 1) % 3] = quad[1]; | ||
26 | t1->vertices[(e1 + 2) % 3] = quad[2]; | ||
27 | t1->vertices[(e1 + 3) % 3] = quad[3]; | ||
28 | t2->vertices[(e2 + 1) % 3] = quad[3]; | ||
29 | t2->vertices[(e2 + 2) % 3] = quad[0]; | ||
30 | t2->vertices[(e2 + 3) % 3] = quad[1]; | ||
31 | } | ||
32 | |||
33 | static inline void rotate_neighbors(TriangleMap *t1, TriangleMap *t2, int e1, int e2) { | ||
34 | TriangleMap *neighbors[] = { | ||
35 | t1->neighbors[(e1 + 1) % 3], | ||
36 | t1->neighbors[(e1 + 2) % 3], | ||
37 | t2->neighbors[(e2 + 1) % 3], | ||
38 | t2->neighbors[(e2 + 2) % 3] | ||
39 | }; | ||
40 | |||
41 | t1->neighbors[(e1 + 1) % 3] = neighbors[1]; | ||
42 | t1->neighbors[(e1 + 2) % 3] = neighbors[2]; | ||
43 | t2->neighbors[(e2 + 1) % 3] = neighbors[3]; | ||
44 | t2->neighbors[(e2 + 2) % 3] = neighbors[0]; | ||
45 | trianglemap_replace_neighbor(t1->neighbors[(e1 + 2) % 3], t2, t1); | ||
46 | trianglemap_replace_neighbor(t2->neighbors[(e2 + 2) % 3], t1, t2); | ||
47 | } | ||
48 | |||
49 | 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 | rotate_vertices(t1, t2, e1, e2); | ||
52 | rotate_neighbors(t1, t2, e1, e2); | ||
53 | } | ||
54 | |||
55 | bool quadrilateral_is_delaunay(TriangleMap *t1, TriangleMap *t2) { | ||
56 | return in_circumcircle(t1, t2->vertices[(trianglemap_find_common_edge(t2, t1) + 2) % 3].origin) && | ||
57 | in_circumcircle(t2, t1->vertices[(trianglemap_find_common_edge(t1, t2) + 2) % 3].origin); | ||
58 | } | ||
diff --git a/src/morpher/trianglemap.c b/src/morpher/trianglemap.c new file mode 100644 index 0000000..45f4ade --- /dev/null +++ b/src/morpher/trianglemap.c | |||
@@ -0,0 +1,64 @@ | |||
1 | #include "morpher/trianglemap.h" | ||
2 | #include <stdlib.h> | ||
3 | #include <assert.h> | ||
4 | #include "common/geom.h" | ||
5 | #include "common/mem.h" | ||
6 | |||
7 | TriangleMap *trianglemap_create(CartesianMapping v1, CartesianMapping v2, CartesianMapping v3) { | ||
8 | TriangleMap *triangle = malloc_or_die(sizeof(TriangleMap)); | ||