Add to git.
[c2lib.git] / test_matvec.c
1 /* Test matrix, vector arithmetic.
2  * By Richard W.M. Jones <rich@annexia.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  * $Id: test_matvec.c,v 1.2 2001/11/19 17:10:55 rich Exp $
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <assert.h>
24 #include <math.h>
25
26 #include "pool.h"
27 #include "matvec.h"
28
29 static inline int
30 is_equal (float a, float b)
31 {
32   return fabs (a - b) < 1e-6;
33 }
34
35 static void
36 test_identity_zero ()
37 {
38   pool p = new_subpool (global_pool);
39   float *m = new_identity_matrix (p);
40   float *v = new_zero_vec (p);
41
42   assert (m[0] == 1 && m[1] == 0 && m[2] == 0 && m[3] == 0 &&
43           m[4] == 0 && m[5] == 1 && m[6] == 0 && m[7] == 0 &&
44           m[8] == 0 && m[9] == 0 && m[10] == 1 && m[11] == 0 &&
45           m[12] == 0 && m[13] == 0 && m[14] == 0 && m[15] == 1);
46   assert (v[0] == 0 && v[1] == 0 && v[2] == 0 && v[3] == 1);
47
48   delete_pool (p);
49 }
50
51 static void
52 test_mag_norm ()
53 {
54   float v[3] = {2, 0, 0}, r[3];
55
56   assert (vec_magnitude (v) == 2);
57   assert (vec_magnitude2d (v) == 2);
58
59   vec_normalize (v, r);
60   assert (r[0] == 1 && r[1] == 0 && r[2] == 0);
61
62   vec_normalize2d (v, r);
63   assert (r[0] == 1 && r[1] == 0);
64 }
65
66 static void
67 test_dot_product ()
68 {
69   float v1[3] = { 1, 0, 0 }, v2[3] = { 0, 1, 0 }, v3[3] = { 1, 1, 0 };
70
71   /* Dot product of perpendicular vectors is 0. */
72   assert (vec_dot_product (v1, v2) == 0);
73
74   /* Dot product of identical normal vectors is 1. */
75   assert (vec_dot_product (v1, v1) == 1);
76
77   /* Angle between vectors. */
78   assert (vec_angle_between (v1, v1) == 0);
79   assert (is_equal (vec_angle_between (v1, v2), M_PI/2));
80   assert (is_equal (vec_angle_between (v1, v3), M_PI/4));
81 }
82
83 static void
84 test_point_line ()
85 {
86   float p[3], v[3], q[3], d;
87
88   /* Line running along the x axis. */
89   p[0] = 0; p[1] = 0; p[2] = 0; v[0] = 1; v[1] = 0; v[2] = 0;
90
91   q[0] = 0; q[1] = 0; q[2] = 0;
92   assert (point_distance_to_line (q, p, v) == 0);
93
94   q[0] = 1; q[1] = 0; q[2] = 0;
95   assert (point_distance_to_line (q, p, v) == 0);
96
97   q[0] = 0; q[1] = 1; q[2] = 0;
98   assert (point_distance_to_line (q, p, v) == 1);
99
100   q[0] = 0; q[1] = 0; q[2] = 1;
101   assert (point_distance_to_line (q, p, v) == 1);
102
103   q[0] = 2; q[1] = 1; q[2] = 0;
104   assert (point_distance_to_line (q, p, v) == 1);
105
106   /* Line running diagonally x-y. */
107   p[0] = 2; p[1] = 2; p[2] = 0; v[0] = 1; v[1] = 1; v[2] = 0;
108
109   q[0] = 0; q[1] = 0; q[2] = 0;
110   assert (point_distance_to_line (q, p, v) == 0);
111
112   q[0] = 1; q[1] = 0; q[2] = 0;
113   d = point_distance_to_line (q, p, v);
114   assert (is_equal (d * d, 0.5));
115 }
116
117 static void
118 test_point_plane ()
119 {
120   float p[3], q[3], r[3], pl[4];
121
122   p[0] = 0; p[1] = 0; p[2] = 0;
123   q[0] = 2; q[1] = 0; q[2] = 0;
124   r[0] = 2; r[1] = 2; r[2] = 0;
125   plane_coefficients (p, q, r, pl);
126
127   assert (pl[3] == 0);
128   vec_normalize (pl, pl);
129   assert (pl[0] == 0 && pl[1] == 0 && pl[2] == -1);
130
131   assert (point_distance_to_plane (pl, p) == 0);
132   assert (point_distance_to_plane (pl, q) == 0);
133   assert (point_distance_to_plane (pl, r) == 0);
134
135   p[0] = 5; p[1] = 5; p[2] = -3;
136   assert (point_distance_to_plane (pl, p) == 3);
137   assert (point_is_inside_plane (pl, p));
138
139   p[0] = 5; p[1] = 5; p[2] = 3;
140   assert (point_distance_to_plane (pl, p) == -3);
141   assert (!point_is_inside_plane (pl, p));
142 }
143
144 static void
145 test_point_in_face ()
146 {
147   float points[4][3] = {
148     { 0, 0, 0 },
149     { 1, 1, 0 },
150     { 1, 1, 1 },
151     { 0, 0, 1 }
152   };
153   float p[3];
154
155   p[0] = 0.5; p[1] = 0.5; p[2] = 0.5;
156   assert (point_lies_in_face ((float *) points, 4, p));
157
158   p[0] = 0.01; p[1] = 0.01; p[2] = 0.9;
159   assert (point_lies_in_face ((float *) points, 4, p));
160
161   p[0] = 0; p[1] = 0; p[2] = 0;
162   assert (point_lies_in_face ((float *) points, 4, p));
163
164   p[0] = 1; p[1] = 1; p[2] = 1;
165   assert (point_lies_in_face ((float *) points, 4, p));
166
167   p[0] = 1; p[1] = 0; p[2] = 0;
168   assert (!point_lies_in_face ((float *) points, 4, p));
169
170   p[0] = 1; p[1] = 1; p[2] = -1;
171   assert (!point_lies_in_face ((float *) points, 4, p));
172
173   p[0] = 0.5; p[1] = 0.5; p[2] = 2;
174   assert (!point_lies_in_face ((float *) points, 4, p));
175 }
176
177 static void
178 test_point_to_face ()
179 {
180   float points[4][3] = {
181     { 0, 0, 0 },
182     { 1, 0, 0 },
183     { 1, 1, 0 },
184     { 0, 1, 0 }
185   };
186   float p[3];
187   int edge;
188
189   p[0] = 0.5; p[1] = 0.5; p[2] = 0;
190   assert (point_distance_to_face ((float *) points, 4, 0, p, &edge) == 0
191           && edge == -1);
192
193   p[0] = 0.5; p[1] = 0.5; p[2] = 1;
194   assert (point_distance_to_face ((float *) points, 4, 0, p, &edge) == -1
195           && edge == -1);
196
197   p[0] = 0.5; p[1] = 0.5; p[2] = -1;
198   assert (point_distance_to_face ((float *) points, 4, 0, p, &edge) == 1
199           && edge == -1);
200
201   p[0] = -1; p[1] = 0.5; p[2] = 0;
202   assert (point_distance_to_face ((float *) points, 4, 0, p, &edge) == -1
203           && edge == 3);
204 }
205
206 int
207 main ()
208 {
209   test_identity_zero ();
210   test_mag_norm ();
211   test_dot_product ();
212   test_point_line ();
213   test_point_plane ();
214   test_point_in_face ();
215   test_point_to_face ();
216
217   exit (0);
218 }