59 #define GEO_ALGORITHMS_C 63 #include "Algorithms.hh" 64 #include <ACG/Utils/NumLimitsT.hh> 65 #include <ACG/Utils/VSToolsT.hh> 66 #include <ACG/Math/GLMatrixT.hh> 91 template<
typename Scalar>
105 Scalar nx = vu[1]*wu[2] - vu[2]*wu[1],
106 ny = vu[2]*wu[0] - vu[0]*wu[2],
107 nz = vu[0]*wu[1] - vu[1]*wu[0],
113 unsigned char max_coord;
138 if (1.0+ax == 1.0)
return false;
139 _result[1] = 1.0 + (pu[1]*wu[2]-pu[2]*wu[1])/nx - 1.0;
140 _result[2] = 1.0 + (vu[1]*pu[2]-vu[2]*pu[1])/nx - 1.0;
141 _result[0] = 1.0 - _result[1] - _result[2];
147 if (1.0+ay == 1.0)
return false;
148 _result[1] = 1.0 + (pu[2]*wu[0]-pu[0]*wu[2])/ny - 1.0;
149 _result[2] = 1.0 + (vu[2]*pu[0]-vu[0]*pu[2])/ny - 1.0;
150 _result[0] = 1.0 - _result[1] - _result[2];
156 if (1.0+az == 1.0)
return false;
157 _result[1] = 1.0 + (pu[0]*wu[1]-pu[1]*wu[0])/nz - 1.0;
158 _result[2] = 1.0 + (vu[0]*pu[1]-vu[1]*pu[0])/nz - 1.0;
159 _result[0] = 1.0 - _result[1] - _result[2];
172 typename Vec::value_type
177 return 0.25 * ((_v1-_v0)%(_v2-_v0)).sqrnorm();
181 template<
typename Scalar>
187 if(_polygon_points.size() < 3)
194 for(
size_t i = 0; i<_polygon_points.size(); i++)
196 cog += _polygon_points[i];
198 cog /= ((Scalar)_polygon_points.size());
204 while((std::fabs(n[0])<1e-30) & (std::fabs(n[1])<1e-30) & (std::fabs(n[2])<1e-30))
206 n = ( _polygon_points[c] - cog )%(_polygon_points[(c+1)%_polygon_points.size()] - cog );
208 if(c == _polygon_points.size()+1)
210 std::cerr <<
"warning: no valid normal found \n";
218 std::cerr <<
"warning: no valid normal found normal"<< n<<
" norm "<<n.
norm()<<
" \n";
231 if((angle != 0.0) && rotation)
237 std::vector<VectorT<Scalar,2> > rotated_points;
238 for(
size_t i = 0; i<_polygon_points.size(); i++)
241 VectorT<Scalar,4> new_point_4(new_point_3[0], new_point_3[1], new_point_3[2], 0);
242 new_point_4 = R*new_point_4;
248 if((n|(_v1 - _v0)) == 0.0)
259 Scalar alpha = (d - (n|_v0))/(n|(_v1 - _v0));
260 _result = _v0 + alpha*(_v1 - _v0);
263 if(alpha > 1.0 || alpha < 0.0)
268 VectorT<Scalar,4> rotated_result(_result[0] - cog[0], _result[1] - cog[1], _result[2] - cog[2], 0);
269 rotated_result = R*rotated_result;
274 size_t points_count = rotated_points.size();
275 for(
size_t i = 0; i<points_count; i++)
279 VectorT<Scalar,2> mid_e = 0.5 * (rotated_points[((i+1)%points_count)] + rotated_points[i]);
282 int sgn0 = ((n_e|cmp0) < 0 )? -1 : ((n_e|cmp0) > 0);
283 int sgn1 = ((n_e|cmp1) < 0 )? -1 : ((n_e|cmp1) > 0);
285 if(sgn1 != sgn0 && sgn1 != 0)
299 typename Vec::value_type
305 Vec d1(_p-_v0), d2(_v1-_v0), min_v(_v0);
306 typename Vec::value_type t = (d1|d2)/ d2.sqrnorm();
308 if (t > 1.0) d1 = _p - (min_v = _v1);
309 else if (t > 0.0) d1 = _p - (min_v = _v0 + d2*t);
311 if (_min_v) *_min_v = min_v;
318 typename Vec::value_type
319 distPointTriangleSquared(
const Vec& _p,
326 Vec v0v1 = _v1 - _v0;
327 Vec v0v2 = _v2 - _v0;
329 typename Vec::value_type d = n.sqrnorm();
333 if (d < FLT_MIN && d > -FLT_MIN) {
335 const double l0 = v0v1.sqrnorm();
336 const double l1 = v0v2.sqrnorm();
337 const double l2 = (_v2 - _v1).sqrnorm();
338 if (l0 > l1 && l0 > l2) {
341 else if (l1 > l0 && l1 > l2) {
348 std::cerr <<
"distPointTriangleSquared: Degenerated triangle !\n";
352 typename Vec::value_type invD =
typename Vec::value_type(1.0) / d;
357 Vec v1v2 = _v2 - _v1;
358 typename Vec::value_type inv_v0v2_2 =
typename Vec::value_type(1.0) / v0v2.sqrnorm();
359 typename Vec::value_type inv_v0v1_2 =
typename Vec::value_type(1.0) / v0v1.sqrnorm();
360 typename Vec::value_type inv_v1v2_2 =
typename Vec::value_type(1.0) / v1v2.sqrnorm();
365 typename Vec::value_type s01, s02, s12;
366 typename Vec::value_type a = (t | v0v2) * -invD;
367 typename Vec::value_type b = (t | v0v1) * invD;
373 s02 = ( v0v2 | v0p ) * inv_v0v2_2;
376 s01 = ( v0v1 | v0p ) * inv_v0v1_2;
379 }
else if (s01 >= 1.0) {
382 v0p = _v0 + v0v1 * s01;
384 }
else if (s02 > 1.0) {
385 s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2;
388 }
else if (s12 <= 0.0) {
391 v0p = _v1 + v1v2 * s12;
394 v0p = _v0 + v0v2 * s02;
396 }
else if (b < 0.0) {
398 s01 = ( v0v1 | v0p ) * inv_v0v1_2;
401 s02 = ( v0v2 | v0p ) * inv_v0v2_2;
404 }
else if (s02 >= 1.0) {
407 v0p = _v0 + v0v2 * s02;
409 }
else if (s01 > 1.0) {
410 s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2;
413 }
else if (s12 <= 0.0) {
416 v0p = _v1 + v1v2 * s12;
419 v0p = _v0 + v0v1 * s01;
421 }
else if (a+b > 1.0) {
423 s12 = ( v1v2 | ( _p - _v1 )) * inv_v1v2_2;
425 s02 = ( v0v2 | v0p ) * inv_v0v2_2;
428 }
else if (s02 >= 1.0) {
431 v0p = _v0 + v0v2*s02;
433 }
else if (s12 <= 0.0) {
434 s01 = ( v0v1 | v0p ) * inv_v0v1_2;
437 }
else if (s01 >= 1.0) {
440 v0p = _v0 + v0v1 * s01;
443 v0p = _v1 + v1v2 * s12;
447 _nearestPoint = _p - n*((n|v0p) * invD);
448 return (_nearestPoint - _p).sqrnorm();
453 return (_nearestPoint - _p).sqrnorm();
460 typename Vec::value_type
461 distPointTriangleSquared(
const Vec& _p,
467 return distPointTriangleSquared(_p, _v0, _v1, _v2, _nearestPoint,
false);
475 typename Vec::value_type
482 return distPointTriangleSquared(_p, _v0, _v1, _v2, _nearestPoint,
true);
494 template<
typename Scalar>
509 Scalar fA01 = -(d0|d1);
511 Scalar fB0 = (kDiff|d0);
513 Scalar fDet = fabs(fA00*fA11-fA01*fA01);
514 Scalar fB1, fS, fT, fSqrDist, fTmp;
517 if ( fDet >= FLT_MIN )
521 fS = fA01*fB1-fA11*fB0;
522 fT = fA01*fB0-fA00*fB1;
528 if ( fS < 0.0 ) fS = 0.0;
529 else if ( fS > fDet ) fS = fDet;
530 if ( fT < 0.0 ) fT = 0.0;
531 else if ( fT > fDet ) fT = fDet;
544 Scalar fInvDet = 1.0/fDet;
547 fSqrDist = fS*(fA00*fS+fA01*fT+2.0*fB0) +
548 fT*(fA01*fS+fA11*fT+2.0*fB1)+fC;
557 fSqrDist = fA11+2.0*fB1+fC;
559 else if ( -fTmp >= fA00 )
562 fSqrDist = fA00+fA11+fC+2.0*(fB1+fTmp);
567 fSqrDist = fTmp*fS+fA11+2.0*fB1+fC;
579 else if ( -fB0 >= fA00 )
582 fSqrDist = fA00+2.0*fB0+fC;
587 fSqrDist = fB0*fS+fC;
602 fSqrDist = fA00+2.0*fB0+fC;
604 else if ( -fTmp >= fA11 )
607 fSqrDist = fA00+fA11+fC+2.0*(fB0+fTmp);
612 fSqrDist = fTmp*fT+fA00+2.0*fB0+fC;
624 fSqrDist = fA11+2.0*fB1+fC;
629 fSqrDist = fTmp*fS+fA11+2.0*fB1+fC;
639 fSqrDist = fA00+2.0*fB0+fC;
641 else if ( -fTmp >= fA11 )
644 fSqrDist = fA00+fA11+fC+2.0*(fB0+fTmp);
649 fSqrDist = fTmp*fT+fA00+2.0*fB0+fC;
667 fSqrDist = fB0*fS+fC;
677 fSqrDist = fA00+2.0*fB0+fC;
679 else if ( -fTmp >= fA11 )
682 fSqrDist = fA00+fA11+fC+2.0*(fB0+fTmp);
687 fSqrDist = fTmp*fT+fA00+2.0*fB0+fC;
705 else if ( -fB1 >= fA11 )
708 fSqrDist = fA11+2.0*fB1+fC;
713 fSqrDist = fB1*fT+fC;
725 fSqrDist = fA00+fA11+fC+2.0*(fB1+fTmp);
730 fSqrDist = fTmp*fS+fA11+2.0*fB1+fC;
741 else if ( -fB1 >= fA11 )
744 fSqrDist = fA11+2.0*fB1+fC;
749 fSqrDist = fB1*fT+fC;
762 fSqrDist = fA00+2.0*fB0+fC;
767 fSqrDist = fB0*fS+fC;
778 else if ( -fB1 >= fA11 )
781 fSqrDist = fA11+2.0*fB1+fC;
786 fSqrDist = fB1*fT+fC;
804 else if ( -fB0 <= fA00 )
808 fSqrDist = fB0*fS+fC;
818 fSqrDist = fA00+fA11+fC+2.0*(fA01+fB0+fB1);
823 fSqrDist = fA00+2.0*fB0+fC+fT*(fA11*fT+2.0*(fA01+fB1));
834 fSqrDist = fA00+2.0*fB0+fC;
836 else if ( fB0 <= 0.0 )
840 fSqrDist = fB0*fS+fC;
849 fSqrDist = fA11+2.0*fB1+fC;
854 fSqrDist = fC+fT*(2.0*fB1+fA11*fT);
861 if (_min_v0) *_min_v0 = _v00 + fS*d0;
862 if (_min_v1) *_min_v1 = _v10 + fT*d1;
864 return fabs(fSqrDist);
869 template <
typename VectorT ,
typename ValueT >
876 assert( fabs(_pnormal.
norm()) > 0.0000000001) ;
877 return( ( (_point - _porigin) | _pnormal ) );
883 template <
typename VectorT >
886 VectorT direction = ( _end - _start ).normalize();
887 assert( fabs(direction.
norm()) > 0.0000000001) ;
888 const VectorT projected_point = ( ( _point - _start ) | direction ) * direction + _start;
890 if ( ( ( projected_point - _start ) | direction ) > ( ( _end - _start ) | direction ) )
893 if ( ( ( projected_point - _start ) | direction ) < 0 )
896 return projected_point;
901 template <
typename VectorT >
908 return (_point - _pnormal * distPointPlane< VectorT , double >( _porigin , _pnormal , _point ) );
914 template<
typename Scalar>
924 G((_v0+_v1+_v2)/3.0);
938 _result = (Scalar)0.5 * ((Scalar)3.0*G - H);
948 template<
typename Scalar>
958 Scalar denom = 4.0*((v0v1%v0v2).sqrnorm());
963 return ( v0v1.sqrnorm() *
971 template<
typename Scalar>
988 _axis = (v0 % v1).normalize();
991 if ( std::isnan(_axis[0]) || std::isnan(_axis[1]) || std::isnan(_axis[2]) ) {
996 _angle = acos(v0 | v1);
999 if ( std::isnan(_angle) )
1004 _angle *= 180.0 / M_PI;
1012 template<
class VectorT>
1017 const double a0 = ((_p1-_p0)|(_p2-_p0));
1019 if ( a0<0.0)
return 1;
1022 const double a1 = ((_p0-_p1)|(_p2-_p1));
1024 if (a1 < 0.0 )
return 2;
1027 const double a2 = ((_p0-_p2)|(_p1-_p2));
1029 if (a2 < 0.0 )
return 3;
1038 template<
typename Scalar>
1058 _center = (_v0+_v1)*0.5;
1059 _radius = 0.5 * c.
norm();
1064 _center = (_v1+_v2)*0.5;
1065 _radius = 0.5 * a.
norm();
1070 _center = (_v2+_v0)*0.5;
1071 _radius = 0.5 * b.
norm();
1088 _center = (Scalar)0.5 * ((Scalar)3.0*G - H);
1089 _radius = (_center-_v0).norm();
1098 template<
typename Scalar>
1108 Scalar denom = 4.0*((v0v1%v0v2).sqrnorm());
1113 Scalar l0 = v0v1.sqrnorm(),
1114 l1 = v0v2.sqrnorm(),
1116 l3 = l0*l1*l2/denom;
1118 return std::max(std::max(l0, l1), std::max(l2, l3));
1125 template<
typename Scalar>
1138 Scalar denom = ((v0v1[0]*v0v2[1]*v0v3[2] +
1139 v0v1[1]*v0v2[2]*v0v3[0] +
1140 v0v1[2]*v0v2[0]*v0v3[1]) -
1141 (v0v1[0]*v0v2[2]*v0v3[1] +
1142 v0v1[1]*v0v2[0]*v0v3[2] +
1143 v0v1[2]*v0v2[1]*v0v3[0])) * 2.0;
1149 _result = _v0 + (( v0v3.sqrnorm()*(v0v1%v0v2) +
1150 v0v2.sqrnorm()*(v0v3%v0v1) +
1151 v0v1.sqrnorm()*(v0v2%v0v3) ) / denom);
1160 template <
typename Scalar>
1164 if (fabs(v[0]) < fabs(v[1])) {
1165 if (fabs(v[0]) < fabs(v[2]))
1166 return VectorT<Scalar, 3>(Scalar(1.0) - v[0] * v[0], -v[0] * v[1], -v[0] * v[2]).normalize();
1168 if (fabs(v[1]) < fabs(v[2]))
1169 return VectorT<Scalar, 3>(-v[1] * v[0], Scalar(1.0) - v[1] * v[1], -v[1] * v[2]).normalize();
1172 return VectorT<Scalar, 3>(-v[2] * v[0], -v[2] * v[1], Scalar(1.0) - v[2] * v[2]).normalize();
1181 template<
typename Scalar>
1189 Scalar v0(_v[0]-_u[0]), v1(_v[1]-_u[1]),
1190 w0(_w[0]-_u[0]), w1(_w[1]-_u[1]),
1191 p0(_p[0]-_u[0]), p1(_p[1]-_u[1]),
1192 denom = v0*w1-v1*w0;
1194 if (1.0+fabs(denom) == 1.0) {
1195 std::cerr <<
"degen tri: (" 1202 _result[1] = 1.0 + ((p0*w1-p1*w0)/denom) - 1.0;
1203 _result[2] = 1.0 + ((v0*p1-v1*p0)/denom) - 1.0;
1204 _result[0] = 1.0 - _result[1] - _result[2];
1213 template<
typename Scalar>
1222 _t1 = ((_v0[1]-_v2[1])*(_v3[0]-_v2[0])-(_v0[0]-_v2[0])*(_v3[1]-_v2[1])) /
1223 ((_v1[0]-_v0[0])*(_v3[1]-_v2[1])-(_v1[1]-_v0[1])*(_v3[0]-_v2[0]));
1225 _t2 = ((_v0[1]-_v2[1])*(_v1[0]-_v0[0])-(_v0[0]-_v2[0])*(_v1[1]-_v0[1])) /
1226 ((_v1[0]-_v0[0])*(_v3[1]-_v2[1])-(_v1[1]-_v0[1])*(_v3[0]-_v2[0]));
1228 return ((_t1>0.0) && (_t1<1.0) && (_t2>0.0) && (_t2<1.0));
1234 template<
typename Scalar>
1241 Scalar x0(_v0[0]), y0(_v0[1]), xy0(x0*x0+y0*y0),
1242 x1(_v1[0]), y1(_v1[1]), xy1(x1*x1+y1*y1),
1243 x2(_v2[0]), y2(_v2[1]), xy2(x2*x2+y2*y2),
1244 a(x0*y1 - x0*y2 - x1*y0 + x1*y2 + x2*y0 - x2*y1),
1245 b(xy0*y1 - xy0*y2 - xy1*y0 + xy1*y2 + xy2*y0 - xy2*y1),
1246 c(xy0*x1 - xy0*x2 - xy1*x0 + xy1*x2 + xy2*x0 - xy2*x1);
1248 if (Scalar(1.0)+a == Scalar(1.0)) {
1249 std::cerr <<
"circumcircle: colinear points\n";
1253 _result[0] = 0.5*b/a;
1254 _result[1] = -0.5*c/a;
1264 template <
typename Scalar,
int N>
1274 Scalar l2, maxl2 = d0.
sqrnorm();
1275 if ((l2=d1.
sqrnorm()) > maxl2)
1279 if ((l2=d1.
sqrnorm()) > maxl2)
1283 Scalar a2 = (d0 % d1).sqrnorm();
1293 return sqrt( (maxl2 * maxl2) / a2 );
1300 template <
typename Scalar,
int N>
1306 const double FOUR_ROOT3 = 6.928203230275509;
1308 double area = 0.5*((_v1-_v0)%(_v2-_v0)).norm();
1310 return (Scalar) (FOUR_ROOT3 * area / ((_v0-_v1).sqrnorm() +
1311 (_v1-_v2).sqrnorm() +
1312 (_v2-_v0).sqrnorm() ));
1315 template<
typename Vec>
1322 typename Vec::value_type& _t,
1323 typename Vec::value_type& _u,
1324 typename Vec::value_type& _v )
1327 Vec edge1, edge2, tvec, pvec, qvec;
1328 typename Vec::value_type det, inv_det;
1335 pvec = _dir % edge2;
1340 if (det > -0.000001 && det < 0.000001)
1342 inv_det =
typename Vec::value_type(1.0) / det;
1348 _u = (tvec | pvec) * inv_det;
1349 if (_u < 0.0 || _u > 1.0)
1353 qvec = tvec % edge1;
1356 _v = (_dir | qvec) * inv_det;
1357 if (_v < 0.0 || _u + _v > 1.0)
1361 _t = (edge2 | qvec) * inv_det;
1365 template<
typename Vec>
1371 typename Vec::value_type& tmin,
1372 typename Vec::value_type& tmax )
1383 typename Vec::value_type tymin, tymax, tzmin, tzmax;
1386 inv_dir[0] = 1/_dir[0];
1387 inv_dir[1] = 1/_dir[1];
1388 inv_dir[2] = 1/_dir[2];
1390 if (inv_dir[0] >= 0) {
1391 tmin = (_bbmin[0] - _o[0]) * inv_dir[0];
1392 tmax = (_bbmax[0] - _o[0]) * inv_dir[0];
1395 tmin = (_bbmax[0] - _o[0]) * inv_dir[0];
1396 tmax = (_bbmin[0] - _o[0]) * inv_dir[0];
1399 if (inv_dir[1] >= 0) {
1400 tymin = (_bbmin[1] - _o[1]) * inv_dir[1];
1401 tymax = (_bbmax[1] - _o[1]) * inv_dir[1];
1404 tymin = (_bbmax[1] - _o[1]) * inv_dir[1];
1405 tymax = (_bbmin[1] - _o[1]) * inv_dir[1];
1408 if ( (tmin > tymax) || (tymin > tmax) )
1415 if (inv_dir[2] >= 0) {
1416 tzmin = (_bbmin[2] - _o[2]) * inv_dir[2];
1417 tzmax = (_bbmax[2] - _o[2]) * inv_dir[2];
1420 tzmin = (_bbmax[2] - _o[2]) * inv_dir[2];
1421 tzmax = (_bbmin[2] - _o[2]) * inv_dir[2];
1424 if ( (tmin > tzmax) || (tzmin > tmax) )
Scalar distLineLineSquared(const VectorT< Scalar, 3 > &_v00, const VectorT< Scalar, 3 > &_v01, const VectorT< Scalar, 3 > &_v10, const VectorT< Scalar, 3 > &_v11, VectorT< Scalar, 3 > *_min_v0, VectorT< Scalar, 3 > *_min_v1, bool _fastApprox)
squared distance of lines (_v00, _v01) and (_v10, _v11)
Scalar minRadiusSquared(const VectorT< Scalar, 3 > &_v0, const VectorT< Scalar, 3 > &_v1, const VectorT< Scalar, 3 > &_v2)
return squared radius of min. enclosing circle of triangle (_v0,_v1,_v2)
Vec::value_type distPointLineSquared(const Vec &_p, const Vec &_v0, const Vec &_v1, Vec *_min_v)
squared distance from point _p to line segment (_v0,_v1)
Scalar aspectRatio(const VectorT< Scalar, N > &_v0, const VectorT< Scalar, N > &_v1, const VectorT< Scalar, N > &_v2)
return aspect ratio (length/height) of triangle
VectorT projectToEdge(const VectorT &_start, const VectorT &_end, const VectorT &_point)
bool lineIntersection(const VectorT< Scalar, 2 > &_v0, const VectorT< Scalar, 2 > &_v1, const VectorT< Scalar, 2 > &_v2, const VectorT< Scalar, 2 > &_v3, Scalar &_t1, Scalar &_t2)
intersect two line segments (_v0,_v1) and (_v2,_v3)
bool baryCoord(const VectorT< Scalar, 3 > &_p, const VectorT< Scalar, 3 > &_u, const VectorT< Scalar, 3 > &_v, const VectorT< Scalar, 3 > &_w, VectorT< Scalar, 3 > &_result)
Scalar circumRadiusSquared(const VectorT< Scalar, 3 > &_v0, const VectorT< Scalar, 3 > &_v1, const VectorT< Scalar, 3 > &_v2)
return squared radius of circumcircle of triangle (_v0,_v1,_v2)
static Scalar min()
Return the smallest absolte value a scalar type can store.
void rotate(Scalar angle, Scalar x, Scalar y, Scalar z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
void identity()
setup an identity matrix
ValueT distPointPlane(const VectorT &_porigin, const VectorT &_pnormal, const VectorT &_point)
Checks the distance from a point to a plane.
Vec::value_type distPointTriangleSquaredStable(const Vec &_p, const Vec &_v0, const Vec &_v1, const Vec &_v2, Vec &_nearestPoint)
squared distance from point _p to triangle (_v0, _v1, _v2)
bool circumCenter(const VectorT< Scalar, 3 > &_v0, const VectorT< Scalar, 3 > &_v1, const VectorT< Scalar, 3 > &_v2, VectorT< Scalar, 3 > &_result)
return circumcenter of triangle (_v0,_v1,_v2)
bool triangleIntersection(const Vec &_o, const Vec &_dir, const Vec &_v0, const Vec &_v1, const Vec &_v2, typename Vec::value_type &_t, typename Vec::value_type &_u, typename Vec::value_type &_v)
Intersect a ray and a triangle.
4x4 matrix implementing OpenGL commands.
Namespace providing different geometric functions concerning angles.
bool minSphere(const VectorT< Scalar, 3 > &_v0, const VectorT< Scalar, 3 > &_v1, const VectorT< Scalar, 3 > &_v2, VectorT< Scalar, 3 > &_center, Scalar &_radius)
construct min. enclosing sphere
bool edgeConvexPolygonIntersection(std::vector< VectorT< Scalar, 3 > > _polygon_points, VectorT< Scalar, 3 > _v0, VectorT< Scalar, 3 > _v1, VectorT< Scalar, 3 > &_result)
Get intersection point of a ray and a convex polygon.
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
int isObtuse(const VectorT &_p0, const VectorT &_p1, const VectorT &_p2)
auto norm() const -> decltype(std::sqrt(std::declval< VectorT< S, DIM >>().sqrnorm()))
compute euclidean norm
decltype(std::declval< S >()*std::declval< S >()) sqrnorm() const
compute squared euclidean norm
Scalar roundness(const VectorT< Scalar, N > &_v0, const VectorT< Scalar, N > &_v1, const VectorT< Scalar, N > &_v2)
return roundness of triangle: 1=equilateral, 0=colinear
VectorT projectToPlane(const VectorT &_porigin, const VectorT &_pnormal, const VectorT &_point)
projects a point to a plane
bool rotationOfTwoVectors(const VectorT< Scalar, 3 > &_v0, const VectorT< Scalar, 3 > &_v1, VectorT< Scalar, 3 > &_axis, Scalar &_angle, bool _degree)
Get rotation axis and signed angle of rotation between two vectors.
bool axisAlignedBBIntersection(const Vec &_o, const Vec &_dir, const Vec &_bbmin, const Vec &_bbmax, typename Vec::value_type &tmin, typename Vec::value_type &tmax)
Intersect a ray and an axis aligned bounding box.
VectorT< Scalar, 3 > perpendicular(const VectorT< Scalar, 3 > &v)
find a vector that's perpendicular to _v
Vec::value_type triangleAreaSquared(const Vec &_v0, const Vec &_v1, const Vec &_v2)
return squared area of triangle (_v0, _v1, _v2)