39 static const double EPSILON = 1e-8;
42 static const double INFINITY = std::numeric_limits<double>::max();;
46 #define DEPRECATED __attribute__((deprecated))
47 #elif defined(_MSC_VER)
48 #define DEPRECATED __declspec(deprecated)
50 #pragma message("WARNING: You need to implement DEPRECATED for this compiler")
60 using CGLA::sqr_length;
61 using CGLA::normalize;
63 inline double min(
double x,
double y)
65 return std::min(x, y);
68 inline double max(
double x,
double y)
70 return std::max(x, y);
76 vec3 n = cross(ab, ac);
78 assert(!isnan(n[0]) && !isnan(n[1]) && !isnan(n[2]));
84 inline int sign(
double val)
86 return (0. < val) - (val < 0.);
92 inline double area(
const vec3& v0,
const vec3& v1,
const vec3& v2)
94 return 0.5 * length(cross(v1-v0, v2-v0));
97 inline double signed_volume(
const vec3& a,
const vec3& b,
const vec3& c,
const vec3& d)
99 return dot(a-d, cross(b-d, c-d))/6.;
102 inline double volume(
const vec3& a,
const vec3& b,
const vec3& c,
const vec3& d)
104 return std::abs(signed_volume(a, b, c, d));
110 inline double cos_angle(
const vec3& a,
const vec3& b,
const vec3& c)
112 vec3 ab = normalize(b - a);
113 vec3 ac = normalize(c - a);
120 inline double angle(
const vec3& a,
const vec3& b,
const vec3& c)
122 return acos(cos_angle(a, b, c));
128 inline mat3 rotation_matrix(
int dimension,
double angle)
136 m[1][1] = cos(angle);
137 m[1][2] = sin(angle);
138 m[2][1] = -sin(angle);
139 m[2][2] = cos(angle);
142 m[0][0] = cos(angle);
143 m[0][2] = -sin(angle);
144 m[2][0] = sin(angle);
145 m[2][2] = cos(angle);
149 m[0][0] = cos(angle);
150 m[0][1] = sin(angle);
151 m[1][0] = -sin(angle);
152 m[1][1] = cos(angle);
163 inline mat3 d_rotation_matrix(
int dimension,
double angle)
170 m[1][1] = -sin(angle);
171 m[1][2] = cos(angle);
172 m[2][1] = -cos(angle);
173 m[2][2] = -sin(angle);
176 m[0][0] = -sin(angle);
177 m[0][2] = -cos(angle);
178 m[2][0] = cos(angle);
179 m[2][2] = -sin(angle);
182 m[0][0] = -sin(angle);
183 m[0][1] = cos(angle);
184 m[1][0] = -cos(angle);
185 m[1][1] = -sin(angle);
195 inline std::vector<double> cos_angles(
const vec3& a,
const vec3& b,
const vec3& c)
197 std::vector<double> cosines(3);
198 cosines[0] = cos_angle(a, b, c);
199 cosines[1] = cos_angle(b, c, a);
200 cosines[2] = cos_angle(c, a, b);
204 inline double cos_min_angle(
const vec3& a,
const vec3& b,
const vec3& c)
206 std::vector<double> cosines = cos_angles(a, b, c);
207 double max_cos = -1.;
208 for(
auto cos : cosines)
210 max_cos = std::max(cos, max_cos);
215 inline double min_angle(
const vec3& a,
const vec3& b,
const vec3& c)
217 return acos(cos_min_angle(a, b, c));
220 inline double cos_max_angle(
const vec3& a,
const vec3& b,
const vec3& c)
222 std::vector<double> cosines = cos_angles(a, b, c);
224 for(
auto cos : cosines)
226 min_cos = std::min(cos, min_cos);
231 inline double max_angle(
const vec3& a,
const vec3& b,
const vec3& c)
233 return std::acos(cos_max_angle(a, b, c));
239 inline double cos_dihedral_angle(
const vec3& a,
const vec3& b,
const vec3& c,
const vec3& d)
241 vec3 n0 = normal_direction(a, b, c);
242 vec3 n1 = normal_direction(b, a, d);
243 double angle = dot(n0, n1);
245 assert(angle < 1. + EPSILON);
246 assert(angle > -1. - EPSILON);
254 inline double dihedral_angle(
const vec3& a,
const vec3& b,
const vec3& c,
const vec3& d)
256 return std::acos(cos_dihedral_angle(a, b, c, d));
266 return (a + b + c)/3.;
271 return (a + b + c + d)*0.25;
277 inline std::vector<double> barycentric_coords(
const vec3& p,
const vec3& a,
const vec3& b,
const vec3& c)
282 double d00 = dot(v0, v0);
283 double d01 = dot(v0, v1);
284 double d11 = dot(v1, v1);
285 double d20 = dot(v2, v0);
286 double d21 = dot(v2, v1);
287 double denom = d00 * d11 - d01 * d01;
289 assert(std::abs(denom) > EPSILON);
291 std::vector<double> coords(3);
292 coords[1] = (d11 * d20 - d01 * d21) / denom;
293 coords[2] = (d00 * d21 - d01 * d20) / denom;
294 coords[0] = 1. - coords[1] - coords[2];
302 inline std::vector<double> barycentric_coords(
const vec3& p,
const vec3& a,
const vec3& b,
const vec3& c,
const vec3& d)
304 std::vector<double> coords(4);
305 coords[0] = signed_volume(p, b, c, d);
306 coords[1] = signed_volume(a, p, c, d);
307 coords[2] = signed_volume(a, b, p, d);
308 coords[3] = signed_volume(a, b, c, p);
310 double s = coords[0] + coords[1] + coords[2] + coords[3];
311 for (
unsigned int i = 0; i < 4; ++i)
321 vec3 n = normal_direction(a, b, c);
322 vec3 bf = barycenter(a, b, c);
323 vec3 bt = barycenter(a, b, c, d);
324 vec3 v_out = bf - bt;
325 if (dot(v_out, n) > 0)
337 return a + v * dot(v1,v)/dot(v, v);
343 inline vec3 project_point_linesegment(
const vec3& p,
const vec3& a,
const vec3& b)
347 double d = dot(v1,v2)/dot(v2,v2);
362 inline vec3 project_point_plane(
const vec3& p,
const vec3& a,
const vec3& n)
364 return p - n * dot(p - a, n);
372 vec3 normal = normal_direction(a, b, c);
373 return project_point_plane(p, a, normal);
379 inline vec3 closest_point_on_triangle(
const vec3& p,
const vec3& a,
const vec3& b,
const vec3& c)
381 auto bc = Util::barycentric_coords(p, a, b, c);
382 bool b1 = bc[0] > -EPSILON, b2 = bc[1] > -EPSILON, b3 = bc[2] > -EPSILON;
385 return project_point_plane(p, a, b, c);
389 return project_point_linesegment(p, b, c);
393 return project_point_linesegment(p, a, c);
397 return project_point_linesegment(p, a, b);
415 inline double ms_length(
const vec3& a,
const vec3& b,
const vec3& c,
const vec3& d)
418 result += sqr_length(a - b);
419 result += sqr_length(a - c);
420 result += sqr_length(a - d);
421 result += sqr_length(b - c);
422 result += sqr_length(b - d);
423 result += sqr_length(c - d);
427 inline double rms_length(
const vec3& a,
const vec3& b,
const vec3& c,
const vec3& d)
429 return sqrt(ms_length(a, b, c, d));
434 inline double quality(
const vec3& a,
const vec3& b,
const vec3& c,
const vec3& d)
436 double v = signed_volume(a, b, c, d);
437 double lrms = rms_length(a, b, c, d);
439 double q = 8.48528 * v / (lrms * lrms * lrms);
449 inline bool is_inside(
const vec3& p,
const vec3& a,
const vec3& normal)
451 if(sqr_length(p-a) == 0.)
455 return dot(p-a, normal) <= 0.;
461 inline bool is_inside(
const vec3& p,
const vec3& a,
const vec3& b,
const vec3& c)
463 auto bc = barycentric_coords(p, a, b, c);
464 return bc[0] > -EPSILON && bc[1] > -EPSILON && bc[2] > -EPSILON;
470 inline bool is_inside(
const vec3& p, std::vector<vec3> corners)
472 while(corners.size() > 2)
474 if(is_inside(p, corners[0], corners[1], corners[2]))
478 corners.erase(corners.begin() + 1);
486 inline bool is_on_same_side(
const vec3& p1,
const vec3& p2,
const vec3& a,
const vec3& normal)
488 auto d1 = dot(p1 - a, normal);
489 auto d2 = dot(p2 - a, normal);
490 if(std::abs(d1) > EPSILON && std::abs(d2) > EPSILON && sign(d1) == sign(d2))
500 inline double distance_point_linesegment(
const vec3& p,
const vec3& a,
const vec3& b)
504 double d = dot(v1, v2)/sqr_length(v2);
507 return length(p - a);
511 return length(p - b);
513 return length(v1 - v2 * d);
519 inline double distance_linesegment_linesegment(
const vec3& a,
const vec3& b,
const vec3& c,
const vec3& d)
524 double duu = dot(u,u);
525 double duv = dot(u,v);
526 double dvv = dot(v,v);
527 double duw = dot(u,w);
528 double dvw = dot(v,w);
529 double D = duu*dvv - duv*duv;
530 double sc, sN, sD = D;
531 double tc, tN, tD = D;
541 sN = (duv*dvw - dvv*duw);
542 tN = (duu*dvw - duv*duw);
570 if ((-duw + duv) < 0.0)
572 else if ((-duw + duv) > duu)
580 sc = (std::abs(sN) < EPSILON ? 0.0 : sN / sD);
581 tc = (std::abs(tN) < EPSILON ? 0.0 : tN / tD);
584 vec3 dP = w + (sc * u) - (tc * v);
592 inline double distance_point_line(
const vec3& p,
const vec3& a,
const vec3& v)
595 return length(v1 - v * dot(v1,v));
601 inline double distance_point_plane(
const vec3& p,
const vec3& a,
const vec3& n)
603 return std::abs(dot(p - a, n));
609 inline double distance_point_triangle(
const vec3& p,
const vec3& a,
const vec3& b,
const vec3& c)
611 vec3 p_proj = project_point_plane(p, a, b, c);
612 if(is_inside(p_proj, a, b, c))
614 return length(p_proj - p);
617 double d_line_ab = distance_point_linesegment(p, a, b);
618 double d_line_bc = distance_point_linesegment(p, b, c);
619 double d_line_ca = distance_point_linesegment(p, c, a);
621 return std::min(std::min(d_line_ab, d_line_bc), d_line_ca);
627 inline double distance_triangle_triangle(
const vec3& a,
const vec3& b,
const vec3& c,
const vec3& d,
const vec3& e,
const vec3& f)
630 double dist = distance_point_triangle(a, d, e, f);
631 dist = std::min(dist, distance_point_triangle(b, d, e, f));
632 dist = std::min(dist, distance_point_triangle(c, d, e, f));
633 dist = std::min(dist, distance_point_triangle(d, a, b, c));
634 dist = std::min(dist, distance_point_triangle(e, a, b, c));
635 dist = std::min(dist, distance_point_triangle(f, a, b, c));
638 dist = std::min(dist, distance_linesegment_linesegment(a, b, d, e));
639 dist = std::min(dist, distance_linesegment_linesegment(a, b, d, f));
640 dist = std::min(dist, distance_linesegment_linesegment(a, b, e, f));
641 dist = std::min(dist, distance_linesegment_linesegment(a, c, d, e));
642 dist = std::min(dist, distance_linesegment_linesegment(a, c, d, f));
643 dist = std::min(dist, distance_linesegment_linesegment(a, c, e, f));
644 dist = std::min(dist, distance_linesegment_linesegment(b, c, d, e));
645 dist = std::min(dist, distance_linesegment_linesegment(b, c, d, f));
646 dist = std::min(dist, distance_linesegment_linesegment(b, c, e, f));
654 inline double intersection_ray_plane(
const vec3& p,
const vec3& r,
const vec3& a,
const vec3& normal)
656 double n = dot(normal, a - p);
657 double d = dot(normal, r);
659 if (std::abs(d) < EPSILON)
661 if (std::abs(n) < EPSILON)
675 inline double intersection_ray_plane(
const vec3& p,
const vec3& r,
const vec3& a,
const vec3& b,
const vec3& c)
677 vec3 normal = normal_direction(a, b, c);
678 return intersection_ray_plane(p, r, a, normal);
684 inline double intersection_ray_triangle(
const vec3& p,
const vec3& r,
const vec3& a,
const vec3& b,
const vec3& c)
686 double t = intersection_ray_plane(p, r, a, b, c);
692 std::vector<double> coords = barycentric_coords(p + t*r, a, b, c);
693 if(coords[0] > EPSILON && coords[1] > EPSILON && coords[2] > EPSILON)
703 inline std::string concat4digits(std::string name,
int number)
705 std::ostringstream s;
707 s << name <<
"000" << number;
708 else if (number < 100)
709 s << name <<
"00" << number;
710 else if (number < 1000)
711 s << name <<
"0" << number;
720 inline double max_diff(
const std::vector<double>& x,
const std::vector<double>& y)
722 double max_diff = -INFINITY;
723 for (
unsigned int i = 0; i < x.size(); i++)
726 max_diff = max(std::abs(x[i] - y[i]), max_diff);
4x4 double matrix.
Definition: Mat4x4d.h:29
A 3D double vector.
Definition: Vec3d.h:26
3 by 3 double matrix.
Definition: Mat3x3d.h:24
A four dimensional floating point vector.
Definition: Vec4d.h:25
2D double floating point vector
Definition: Vec2d.h:23