summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpacien2017-12-22 01:57:03 +0100
committerpacien2017-12-22 01:57:25 +0100
commit553dc4a5b272a1828940e72a07b1c9a7210be464 (patch)
tree0dfaf1b2e3229e064258e4dc5c117a1250f40f87
parenta767c658cb603de9ec9f0577627b9b32cbf82b2b (diff)
downloadmorpher-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.h39
-rw-r--r--include/morpher/trianglemap.h123
-rw-r--r--src/morpher/quadrilateral.c58
-rw-r--r--src/morpher/trianglemap.c64
-rw-r--r--test/morpher/quadrilateral.c71
-rw-r--r--test/morpher/trianglemap.c71
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 */
24void 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 */
37bool 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 */
21typedef 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 */
39TriangleMap *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 */
53TriangleMap *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 */
67TriangleMap *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 */
80int 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 */
95void 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 */
106void 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 */
121TriangleMap *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
5static inline IntVector p2(IntVector n) {
6 return n * n;
7}
8
9static 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
17static 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
33static 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
49void 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
55bool 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
7TriangleMap *trianglemap_create(CartesianMapping v1, CartesianMapping v2, CartesianMapping v3) {
8 TriangleMap *triangle = malloc_or_die(sizeof(TriangleMap));