faunus
basic_types_and_functions.h
1 #ifndef VORONOTALT_BASIC_TYPES_AND_FUNCTIONS_H_
2 #define VORONOTALT_BASIC_TYPES_AND_FUNCTIONS_H_
3 
4 #include <cmath>
5 
6 //#define VORONOTALT_FP32
7 #define VORONOTALT_UI32
8 
9 #ifdef VORONOTALT_FP32
10 #define FLOATCONST( v ) v ## f
11 #define FLOATEPSILON 0.000001f
12 #define PIVALUE 3.14159265358979323846f
13 #else
14 #define FLOATCONST( v ) v
15 #define FLOATEPSILON 0.0000000001
16 #define PIVALUE 3.14159265358979323846
17 #endif
18 
19 namespace voronotalt
20 {
21 
22 #ifdef VORONOTALT_FP32
23 typedef float Float;
24 #else
25 typedef double Float;
26 #endif
27 
28 #ifdef VORONOTALT_UI32
29 typedef unsigned int UnsignedInt;
30 #else
31 typedef std::size_t UnsignedInt;
32 #endif
33 
35 {
36  Float x;
37  Float y;
38  Float z;
39 
40  SimplePoint() noexcept : x(FLOATCONST(0.0)), y(FLOATCONST(0.0)), z(FLOATCONST(0.0))
41  {
42  }
43 
44  SimplePoint(const Float x, const Float y, const Float z) noexcept : x(x), y(y), z(z)
45  {
46  }
47 };
48 
50 {
51  SimplePoint p;
52  Float r;
53 
54  SimpleSphere() noexcept : r(FLOATCONST(0.0))
55  {
56  }
57 
58  SimpleSphere(const SimplePoint& p, const Float r) noexcept : p(p), r(r)
59  {
60  }
61 
62  SimpleSphere(const Float x, const Float y, const Float z, const Float r) noexcept : p(x, y, z), r(r)
63  {
64  }
65 };
66 
68 {
69  Float a;
70  Float b;
71  Float c;
72  Float d;
73 
74  SimpleQuaternion(const Float a, const Float b, const Float c, const Float d) noexcept : a(a), b(b), c(c), d(d)
75  {
76  }
77 
78  SimpleQuaternion(const Float a, const SimplePoint& p) noexcept : a(a), b(p.x), c(p.y), d(p.z)
79  {
80  }
81 };
82 
83 struct ValuedID
84 {
85  Float value;
86  UnsignedInt index;
87 
88  ValuedID() noexcept : value(FLOATCONST(0.0)), index(0)
89  {
90  }
91 
92  ValuedID(const Float value, const UnsignedInt index) noexcept : value(value), index(index)
93  {
94  }
95 
96  bool operator<(const ValuedID& cid) const noexcept
97  {
98  return (value<cid.value || (value==cid.value && index<cid.index));
99  }
100 };
101 
102 inline bool equal(const Float a, const Float b, const Float e) noexcept
103 {
104  return (((a-b)<=e) && ((b-a)<=e));
105 }
106 
107 inline bool equal(const Float a, const Float b) noexcept
108 {
109  return equal(a, b, FLOATEPSILON);
110 }
111 
112 inline bool less(const Float a, const Float b) noexcept
113 {
114  return ((a+FLOATEPSILON)<b);
115 }
116 
117 inline bool greater(const Float a, const Float b) noexcept
118 {
119  return ((a-FLOATEPSILON)>b);
120 }
121 
122 inline bool less_or_equal(const Float a, const Float b) noexcept
123 {
124  return (less(a, b) || equal(a, b));
125 }
126 
127 inline bool greater_or_equal(const Float a, const Float b) noexcept
128 {
129  return (greater(a, b) || equal(a, b));
130 }
131 
132 inline void set_close_to_equal(Float& a, const Float b) noexcept
133 {
134  if(equal(a, b))
135  {
136  a=b;
137  }
138 }
139 
140 inline Float squared_distance_from_point_to_point(const SimplePoint& a, const SimplePoint& b) noexcept
141 {
142  const Float dx=(a.x-b.x);
143  const Float dy=(a.y-b.y);
144  const Float dz=(a.z-b.z);
145  return (dx*dx+dy*dy+dz*dz);
146 }
147 
148 inline Float distance_from_point_to_point(const SimplePoint& a, const SimplePoint& b) noexcept
149 {
150  return sqrt(squared_distance_from_point_to_point(a, b));
151 }
152 
153 inline bool point_equals_point(const SimplePoint& a, const SimplePoint& b) noexcept
154 {
155  return (equal(a.x, b.x) && equal(a.y, b.y) && equal(a.z, b.z));
156 }
157 
158 inline Float squared_point_module(const SimplePoint& a) noexcept
159 {
160  return (a.x*a.x+a.y*a.y+a.z*a.z);
161 }
162 
163 inline Float point_module(const SimplePoint& a) noexcept
164 {
165  return sqrt(squared_point_module(a));
166 }
167 
168 inline Float dot_product(const SimplePoint& a, const SimplePoint& b) noexcept
169 {
170  return (a.x*b.x+a.y*b.y+a.z*b.z);
171 }
172 
173 inline SimplePoint cross_product(const SimplePoint& a, const SimplePoint& b) noexcept
174 {
175  return SimplePoint(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
176 }
177 
178 inline SimplePoint point_and_number_product(const SimplePoint& a, const Float k) noexcept
179 {
180  return SimplePoint(a.x*k, a.y*k, a.z*k);
181 }
182 
183 inline SimplePoint unit_point(const SimplePoint& a) noexcept
184 {
185  return ((equal(squared_point_module(a), FLOATCONST(1.0))) ? a : point_and_number_product(a, FLOATCONST(1.0)/point_module(a)));
186 }
187 
188 inline SimplePoint sum_of_points(const SimplePoint& a, const SimplePoint& b) noexcept
189 {
190  return SimplePoint(a.x+b.x, a.y+b.y, a.z+b.z);
191 }
192 
193 inline SimplePoint sub_of_points(const SimplePoint& a, const SimplePoint& b) noexcept
194 {
195  return SimplePoint(a.x-b.x, a.y-b.y, a.z-b.z);
196 }
197 
198 inline Float signed_distance_from_point_to_plane(const SimplePoint& plane_point, const SimplePoint& plane_normal, const SimplePoint& x) noexcept
199 {
200  return dot_product(unit_point(plane_normal), sub_of_points(x, plane_point));
201 }
202 
203 inline int halfspace_of_point(const SimplePoint& plane_point, const SimplePoint& plane_normal, const SimplePoint& x) noexcept
204 {
205  const Float sd=signed_distance_from_point_to_plane(plane_point, plane_normal, x);
206  if(greater(sd, FLOATCONST(0.0)))
207  {
208  return 1;
209  }
210  else if(less(sd, FLOATCONST(0.0)))
211  {
212  return -1;
213  }
214  return 0;
215 }
216 
217 inline SimplePoint intersection_of_plane_and_segment(const SimplePoint& plane_point, const SimplePoint& plane_normal, const SimplePoint& a, const SimplePoint& b) noexcept
218 {
219  const Float da=signed_distance_from_point_to_plane(plane_point, plane_normal, a);
220  const Float db=signed_distance_from_point_to_plane(plane_point, plane_normal, b);
221  if((da-db)==0)
222  {
223  return a;
224  }
225  else
226  {
227  const Float t=da/(da-db);
228  return sum_of_points(a, point_and_number_product(sub_of_points(b, a), t));
229  }
230 }
231 
232 inline Float triangle_area(const SimplePoint& a, const SimplePoint& b, const SimplePoint& c) noexcept
233 {
234  return (point_module(cross_product(sub_of_points(b, a), sub_of_points(c, a)))/FLOATCONST(2.0));
235 }
236 
237 inline Float min_angle(const SimplePoint& o, const SimplePoint& a, const SimplePoint& b) noexcept
238 {
239  Float cos_val=dot_product(unit_point(sub_of_points(a, o)), unit_point(sub_of_points(b, o)));
240  if(cos_val<FLOATCONST(-1.0))
241  {
242  cos_val=FLOATCONST(-1.0);
243  }
244  else if(cos_val>FLOATCONST(1.0))
245  {
246  cos_val=FLOATCONST(1.0);
247  }
248  return std::acos(cos_val);
249 }
250 
251 inline Float directed_angle(const SimplePoint& o, const SimplePoint& a, const SimplePoint& b, const SimplePoint& c) noexcept
252 {
253  const Float angle=min_angle(o, a, b);
254  const SimplePoint n=cross_product(unit_point(sub_of_points(a, o)), unit_point(sub_of_points(b, o)));
255  if(dot_product(sub_of_points(c, o), n)>=0)
256  {
257  return angle;
258  }
259  else
260  {
261  return (PIVALUE*FLOATCONST(2.0)-angle);
262  }
263 }
264 
265 SimplePoint any_normal_of_vector(const SimplePoint& a) noexcept
266 {
267  SimplePoint b=a;
268  if(!equal(b.x, FLOATCONST(0.0)) && (!equal(b.y, FLOATCONST(0.0)) || !equal(b.z, FLOATCONST(0.0))))
269  {
270  b.x=FLOATCONST(0.0)-b.x;
271  return unit_point(cross_product(a, b));
272  }
273  else if(!equal(b.y, FLOATCONST(0.0)) && (!equal(b.x, FLOATCONST(0.0)) || !equal(b.z, FLOATCONST(0.0))))
274  {
275  b.y=FLOATCONST(0.0)-b.y;
276  return unit_point(cross_product(a, b));
277  }
278  else if(!equal(b.x, FLOATCONST(0.0)))
279  {
280  return SimplePoint(FLOATCONST(0.0), FLOATCONST(1.0), FLOATCONST(0.0));
281  }
282  else
283  {
284  return SimplePoint(FLOATCONST(1.0), FLOATCONST(0.0), FLOATCONST(0.0));
285  }
286 }
287 
288 inline bool sphere_intersects_sphere(const SimpleSphere& a, const SimpleSphere& b) noexcept
289 {
290  return less(squared_distance_from_point_to_point(a.p, b.p), (a.r+b.r)*(a.r+b.r));
291 }
292 
293 inline bool sphere_equals_sphere(const SimpleSphere& a, const SimpleSphere& b) noexcept
294 {
295  return (equal(a.r, b.r) && equal(a.p.x, b.p.x) && equal(a.p.y, b.p.y) && equal(a.p.z, b.p.z));
296 }
297 
298 inline bool sphere_contains_sphere(const SimpleSphere& a, const SimpleSphere& b) noexcept
299 {
300  return (greater_or_equal(a.r, b.r) && less_or_equal(squared_distance_from_point_to_point(a.p, b.p), (a.r-b.r)*(a.r-b.r)));
301 }
302 
303 inline Float distance_to_center_of_intersection_circle_of_two_spheres(const SimpleSphere& a, const SimpleSphere& b) noexcept
304 {
305  const Float cm=distance_from_point_to_point(a.p, b.p);
306  const Float cos_g=(a.r*a.r+cm*cm-b.r*b.r)/(2*a.r*cm);
307  return (a.r*cos_g);
308 }
309 
310 inline SimplePoint center_of_intersection_circle_of_two_spheres(const SimpleSphere& a, const SimpleSphere& b) noexcept
311 {
312  const SimplePoint cv=sub_of_points(b.p, a.p);
313  const Float cm=point_module(cv);
314  const Float cos_g=(a.r*a.r+cm*cm-b.r*b.r)/(2*a.r*cm);
315  return sum_of_points(a.p, point_and_number_product(cv, a.r*cos_g/cm));
316 }
317 
318 inline SimpleSphere intersection_circle_of_two_spheres(const SimpleSphere& a, const SimpleSphere& b) noexcept
319 {
320  const SimplePoint cv=sub_of_points(b.p, a.p);
321  const Float cm=point_module(cv);
322  const Float cos_g=(a.r*a.r+cm*cm-b.r*b.r)/(2*a.r*cm);
323  const Float sin_g=std::sqrt(1-cos_g*cos_g);
324  return SimpleSphere(sum_of_points(a.p, point_and_number_product(cv, a.r*cos_g/cm)), a.r*sin_g);
325 }
326 
327 inline bool project_point_inside_line(const SimplePoint& o, const SimplePoint& a, const SimplePoint& b, SimplePoint& result) noexcept
328 {
329  const SimplePoint v=unit_point(sub_of_points(b, a));
330  const Float l=dot_product(v, sub_of_points(o, a));
331  if(l>FLOATCONST(0.0) && (l*l)<=squared_distance_from_point_to_point(a, b))
332  {
333  result=sum_of_points(a, point_and_number_product(v, l));
334  return true;
335  }
336  return false;
337 }
338 
339 inline bool intersect_segment_with_circle(const SimpleSphere& circle, const SimplePoint& p_in, const SimplePoint& p_out, SimplePoint& result) noexcept
340 {
341  const Float dist_in_to_out=distance_from_point_to_point(p_in, p_out);
342  if(dist_in_to_out>FLOATCONST(0.0))
343  {
344  const SimplePoint v=point_and_number_product(sub_of_points(p_in, p_out), FLOATCONST(1.0)/dist_in_to_out);
345  const SimplePoint u=sub_of_points(circle.p, p_out);
346  const SimplePoint s=sum_of_points(p_out, point_and_number_product(v, dot_product(v, u)));
347  const Float ll=(circle.r*circle.r)-squared_distance_from_point_to_point(circle.p, s);
348  if(ll>=FLOATCONST(0.0))
349  {
350  result=sum_of_points(s, point_and_number_product(v, FLOATCONST(0.0)-std::sqrt(ll)));
351  return true;
352  }
353  }
354  return false;
355 }
356 
357 inline Float min_dihedral_angle(const SimplePoint& o, const SimplePoint& a, const SimplePoint& b1, const SimplePoint& b2) noexcept
358 {
359  const SimplePoint oa=unit_point(sub_of_points(a, o));
360  const SimplePoint d1=sub_of_points(b1, sum_of_points(o, point_and_number_product(oa, dot_product(oa, sub_of_points(b1, o)))));
361  const SimplePoint d2=sub_of_points(b2, sum_of_points(o, point_and_number_product(oa, dot_product(oa, sub_of_points(b2, o)))));
362  const Float cos_val=dot_product(unit_point(d1), unit_point(d2));
363  return std::acos(std::max(FLOATCONST(-1.0), std::min(cos_val, FLOATCONST(1.0))));
364 }
365 
366 inline SimpleQuaternion quaternion_product(const SimpleQuaternion& q1, const SimpleQuaternion& q2) noexcept
367 {
368  return SimpleQuaternion(
369  q1.a*q2.a - q1.b*q2.b - q1.c*q2.c - q1.d*q2.d,
370  q1.a*q2.b + q1.b*q2.a + q1.c*q2.d - q1.d*q2.c,
371  q1.a*q2.c - q1.b*q2.d + q1.c*q2.a + q1.d*q2.b,
372  q1.a*q2.d + q1.b*q2.c - q1.c*q2.b + q1.d*q2.a);
373 }
374 
375 inline SimpleQuaternion inverted_quaternion(const SimpleQuaternion& q) noexcept
376 {
377  return SimpleQuaternion(q.a, FLOATCONST(0.0)-q.b, FLOATCONST(0.0)-q.c, FLOATCONST(0.0)-q.d);
378 }
379 
380 inline SimplePoint rotate_point_around_axis(const SimplePoint& axis, const Float angle, const SimplePoint& p) noexcept
381 {
382  if(squared_point_module(axis)>0)
383  {
384  const Float radians_angle_half=(angle*FLOATCONST(0.5));
385  const SimpleQuaternion q1=SimpleQuaternion(std::cos(radians_angle_half), point_and_number_product(unit_point(axis), std::sin(radians_angle_half)));
386  const SimpleQuaternion q2=SimpleQuaternion(FLOATCONST(0.0), p);
387  const SimpleQuaternion q3=quaternion_product(quaternion_product(q1, q2), inverted_quaternion(q1));
388  return SimplePoint(q3.b, q3.c, q3.d);
389  }
390  else
391  {
392  return p;
393  }
394 }
395 
396 }
397 
398 #endif /* VORONOTALT_BASIC_TYPES_AND_FUNCTIONS_H_ */
Definition: basic_types_and_functions.h:34
Definition: basic_types_and_functions.h:83
Definition: basic_types_and_functions.h:67
Definition: basic_types_and_functions.h:19
Definition: basic_types_and_functions.h:49