diff options
-rw-r--r-- | include/common/geom.h | 93 | ||||
-rw-r--r-- | include/common/time.h | 4 | ||||
-rw-r--r-- | src/common/geom.c | 27 | ||||
-rw-r--r-- | src/morpher/trianglemap.c | 2 | ||||
-rw-r--r-- | test/common/geom.c | 21 |
5 files changed, 137 insertions, 10 deletions
diff --git a/include/common/geom.h b/include/common/geom.h index b3564a5..334e95c 100644 --- a/include/common/geom.h +++ b/include/common/geom.h | |||
@@ -15,6 +15,12 @@ | |||
15 | typedef int32_t IntVector; | 15 | typedef int32_t IntVector; |
16 | 16 | ||
17 | /** | 17 | /** |
18 | * Type: RealVector | ||
19 | * An abstract 1-D real vector. | ||
20 | */ | ||
21 | typedef double RealVector; | ||
22 | |||
23 | /** | ||
18 | * Struct: CartesianVector | 24 | * Struct: CartesianVector |
19 | * An abstract 2-D vector in cartesian coordinates. | 25 | * An abstract 2-D vector in cartesian coordinates. |
20 | * | 26 | * |
@@ -27,6 +33,19 @@ typedef struct { | |||
27 | } CartesianVector; | 33 | } CartesianVector; |
28 | 34 | ||
29 | /** | 35 | /** |
36 | * Struct: BarycentricVector | ||
37 | * An abstract barycentric coordinate tuple relative to a triangle. | ||
38 | * The third barycentric coordinate is deduced from the first two ones. | ||
39 | * | ||
40 | * Fields: | ||
41 | * a - the first barycentric coordinate | ||
42 | * b - the second barycentric coordinate | ||
43 | */ | ||
44 | typedef struct { | ||
45 | RealVector a, b; | ||
46 | } BarycentricVector; | ||
47 | |||
48 | /** | ||
30 | * Struct: CartesianMapping | 49 | * Struct: CartesianMapping |
31 | * A tuple of cartesian vectors representing a mapping. | 50 | * A tuple of cartesian vectors representing a mapping. |
32 | * | 51 | * |
@@ -38,6 +57,16 @@ typedef struct { | |||
38 | CartesianVector origin, target; | 57 | CartesianVector origin, target; |
39 | } CartesianMapping; | 58 | } CartesianMapping; |
40 | 59 | ||
60 | /** | ||
61 | * Struct: Triangle | ||
62 | * Represents a simple triangle with three vertices. | ||
63 | * | ||
64 | * Fields: | ||
65 | * v[] - array of vertices | ||
66 | */ | ||
67 | typedef struct { | ||
68 | CartesianVector v[3]; | ||
69 | } Triangle; | ||
41 | 70 | ||
42 | /** | 71 | /** |
43 | * Function: m | 72 | * Function: m |
@@ -66,6 +95,19 @@ CartesianMapping m(int x, int y); | |||
66 | CartesianVector v(int x, int y); | 95 | CartesianVector v(int x, int y); |
67 | 96 | ||
68 | /** | 97 | /** |
98 | * Function: b | ||
99 | * Shorthand for a barycentric vector. | ||
100 | * | ||
101 | * Parameters: | ||
102 | * a - the a-coordinate | ||
103 | * b - the b-coordinate | ||
104 | * | ||
105 | * Returns: | ||
106 | * A barycentric vector | ||
107 | */ | ||
108 | BarycentricVector b(double a, double b); | ||
109 | |||
110 | /** | ||
69 | * Function: mappings_equals | 111 | * Function: mappings_equals |
70 | * Compares two cartesian mappings. | 112 | * Compares two cartesian mappings. |
71 | * | 113 | * |
@@ -92,17 +134,54 @@ bool mappings_equals(CartesianMapping m1, CartesianMapping m2); | |||
92 | bool vector_equals(CartesianVector v1, CartesianVector v2); | 134 | bool vector_equals(CartesianVector v1, CartesianVector v2); |
93 | 135 | ||
94 | /** | 136 | /** |
95 | * Function: triangle_area | 137 | * Function: barycentric_vector_equals |
96 | * Computes the area of a triangle. | 138 | * Compares two barycentric vectors. |
139 | * | ||
140 | * Parameters: | ||
141 | * v1 - the first vector | ||
142 | * v2 - the second vector | ||
143 | * | ||
144 | * Returns: | ||
145 | * T(v1 is equal to v2) | ||
146 | */ | ||
147 | bool barycentric_vector_equals(BarycentricVector b1, BarycentricVector b2); | ||
148 | |||
149 | /** | ||
150 | * Function: square_area | ||
151 | * Computes the area of a square spawned by three positively oriented vertices. | ||
152 | * | ||
153 | * Parameters: | ||
154 | * vi - vertices | ||
155 | * | ||
156 | * Returns: | ||
157 | * The area of the square | ||
158 | */ | ||
159 | IntVector square_area(CartesianVector v1, CartesianVector v2, CartesianVector v3); | ||
160 | |||
161 | /** | ||
162 | * Function: cartesian_to_barycentric | ||
163 | * Computes and returns the barycentric coordinates of a given point in the given reference triangle. | ||
164 | * | ||
165 | * Parameters: | ||
166 | * t - reference triangle | ||
167 | * p - the vector to convert | ||
168 | * | ||
169 | * Returns: | ||
170 | * The barycentric coordinates vector | ||
171 | */ | ||
172 | BarycentricVector cartesian_to_barycentric(Triangle t, CartesianVector p); | ||
173 | |||
174 | /** | ||
175 | * Function: barycentric_to_cartesian | ||
176 | * Computes and returns the cartesian coordinates of a given point in the given reference triangle. | ||
97 | * | 177 | * |
98 | * Parameters: | 178 | * Parameters: |
99 | * v1 - first vertex | 179 | * t - reference triangle |
100 | * v2 - second vertex | 180 | * p - the vector to convert |
101 | * v3 - third vertex | ||
102 | * | 181 | * |
103 | * Returns: | 182 | * Returns: |
104 | * The area of the triangle spawned by the three supplied vertices | 183 | * The cartesian coordinate vector |
105 | */ | 184 | */ |
106 | IntVector triangle_area(CartesianVector v1, CartesianVector v2, CartesianVector v3); | 185 | CartesianVector barycentric_to_cartesian(Triangle t, BarycentricVector p); |
107 | 186 | ||
108 | #endif | 187 | #endif |
diff --git a/include/common/time.h b/include/common/time.h index 54a7bb2..e207ad7 100644 --- a/include/common/time.h +++ b/include/common/time.h | |||
@@ -5,6 +5,8 @@ | |||
5 | * File: time.h | 5 | * File: time.h |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "geom.h" | ||
9 | |||
8 | /** | 10 | /** |
9 | * Constants: Time vectors | 11 | * Constants: Time vectors |
10 | * | 12 | * |
@@ -18,6 +20,6 @@ | |||
18 | * Type: TimeVector | 20 | * Type: TimeVector |
19 | * An abstract time vector. | 21 | * An abstract time vector. |
20 | */ | 22 | */ |
21 | typedef float TimeVector; | 23 | typedef RealVector TimeVector; |
22 | 24 | ||
23 | #endif | 25 | #endif |
diff --git a/src/common/geom.c b/src/common/geom.c index 219270f..eb35727 100644 --- a/src/common/geom.c +++ b/src/common/geom.c | |||
@@ -1,6 +1,12 @@ | |||
1 | #include "common/geom.h" | 1 | #include "common/geom.h" |
2 | #include <math.h> | ||
3 | #include <common/geom.h> | ||
2 | #include "morpher/matrix.h" | 4 | #include "morpher/matrix.h" |
3 | 5 | ||
6 | static inline IntVector int_round(RealVector x) { | ||
7 | return (IntVector) round(x); | ||
8 | } | ||
9 | |||
4 | CartesianMapping m(int x, int y) { | 10 | CartesianMapping m(int x, int y) { |
5 | return (CartesianMapping) {{x, y}, | 11 | return (CartesianMapping) {{x, y}, |
6 | {x, y}}; | 12 | {x, y}}; |
@@ -10,6 +16,10 @@ CartesianVector v(int x, int y) { | |||
10 | return (CartesianVector) {x, y}; | 16 | return (CartesianVector) {x, y}; |
11 | } | 17 | } |
12 | 18 | ||
19 | BarycentricVector b(double a, double b) { | ||
20 | return (BarycentricVector) {a, b}; | ||
21 | } | ||
22 | |||
13 | bool mappings_equals(CartesianMapping m1, CartesianMapping m2) { | 23 | bool mappings_equals(CartesianMapping m1, CartesianMapping m2) { |
14 | return vector_equals(m1.origin, m2.origin) && vector_equals(m1.target, m2.target); | 24 | return vector_equals(m1.origin, m2.origin) && vector_equals(m1.target, m2.target); |
15 | } | 25 | } |
@@ -18,7 +28,22 @@ bool vector_equals(CartesianVector v1, CartesianVector v2) { | |||
18 | return v1.x == v2.x && v1.y == v2.y; | 28 | return v1.x == v2.x && v1.y == v2.y; |
19 | } | 29 | } |
20 | 30 | ||
21 | IntVector triangle_area(CartesianVector v1, CartesianVector v2, CartesianVector v3) { | 31 | bool barycentric_vector_equals(BarycentricVector b1, BarycentricVector b2) { |
32 | return b1.a == b2.a && b1.b == b2.b; | ||
33 | } | ||
34 | |||
35 | IntVector square_area(CartesianVector v1, CartesianVector v2, CartesianVector v3) { | ||
22 | return matrix_int_det2(v1.x - v3.x, v2.x - v3.x, | 36 | return matrix_int_det2(v1.x - v3.x, v2.x - v3.x, |
23 | v1.y - v3.y, v2.y - v3.y); | 37 | v1.y - v3.y, v2.y - v3.y); |
24 | } | 38 | } |
39 | |||
40 | BarycentricVector cartesian_to_barycentric(Triangle t, CartesianVector p) { | ||
41 | RealVector total_area = square_area(t.v[0], t.v[1], t.v[2]); | ||
42 | return (BarycentricVector) {square_area(t.v[1], t.v[2], p) / total_area, | ||
43 | square_area(t.v[2], t.v[0], p) / total_area}; | ||
44 | } | ||
45 | |||
46 | CartesianVector barycentric_to_cartesian(Triangle t, BarycentricVector p) { | ||
47 | return (CartesianVector) {int_round(p.a * (t.v[0].x - t.v[2].x) + p.b * (t.v[1].x - t.v[2].x) + t.v[2].x), | ||
48 | int_round(p.a * (t.v[0].y - t.v[2].y) + p.b * (t.v[1].y - t.v[2].y) + t.v[2].y)}; | ||
49 | } | ||
diff --git a/src/morpher/trianglemap.c b/src/morpher/trianglemap.c index e2f3eb9..ad526bc 100644 --- a/src/morpher/trianglemap.c +++ b/src/morpher/trianglemap.c | |||
@@ -30,7 +30,7 @@ TriangleMap *trianglemap_to(TriangleMap *t, CartesianVector v) { | |||
30 | int edge; | 30 | int edge; |
31 | 31 | ||
32 | for (edge = 0; edge < 3; ++edge) | 32 | for (edge = 0; edge < 3; ++edge) |
33 | if (triangle_area(t->vertices[edge].origin, t->vertices[(edge + 1) % 3].origin, v) > 0) | 33 | if (square_area(t->vertices[edge].origin, t->vertices[(edge + 1) % 3].origin, v) > 0) |
34 | return t->neighbors[edge]; | 34 | return t->neighbors[edge]; |
35 | 35 | ||
36 | return t; | 36 | return t; |
diff --git a/test/common/geom.c b/test/common/geom.c new file mode 100644 index 0000000..f05e0a1 --- /dev/null +++ b/test/common/geom.c | |||
@@ -0,0 +1,21 @@ | |||
1 | #include "common/geom.h" | ||
2 | #include <assert.h> | ||
3 | |||
4 | static void test_square_area() { | ||
5 | assert(square_area(v(0, 0), v(10, 0), v(10, 10)) == 100); | ||
6 | assert(square_area(v(0, 0), v(0, 10), v(10, 10)) == -100); | ||
7 | } | ||
8 | |||
9 | static void test_cartesian_barycentric_vectors() { | ||
10 | Triangle t = {{v(0, 0), v(10, 0), v(10, 10)}}; | ||
11 | CartesianVector c = v(3, 2); | ||