opensurgsim
Geometry.h
Go to the documentation of this file.
1 // This file is a part of the OpenSurgSim project.
2 // Copyright 2013-2017, SimQuest Solutions Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #ifndef SURGSIM_MATH_GEOMETRY_H
17 #define SURGSIM_MATH_GEOMETRY_H
18 
19 #include <boost/container/static_vector.hpp>
20 #include <Eigen/Core>
21 #include <Eigen/Geometry>
22 
23 #include "SurgSim/Framework/Log.h"
24 #include "SurgSim/Math/Polynomial.h"
25 #include "SurgSim/Math/Vector.h"
26 
38 
39 namespace SurgSim
40 {
41 namespace Math
42 {
43 
44 namespace Geometry
45 {
46 
48 static const double DistanceEpsilon = 1e-10;
49 
51 static const double SquaredDistanceEpsilon = 1e-10;
52 
54 static const double AngularEpsilon = 1e-10;
55 
57 static const double ScalarEpsilon = 1e-10;
58 
59 }
60 
67 template <class T, int MOpt> inline
68 bool doesIntersectSegmentSegment(const Eigen::Matrix<T, 2, 1, MOpt>& s0v0,
69  const Eigen::Matrix<T, 2, 1, MOpt>& s0v1,
70  const Eigen::Matrix<T, 2, 1, MOpt>& s1v0,
71  const Eigen::Matrix<T, 2, 1, MOpt>& s1v1,
72  T* s, T* t)
73 {
74  using SurgSim::Math::Geometry::DistanceEpsilon;
75 
76  SURGSIM_ASSERT(s != nullptr) << "Null pointers sent in s variable";
77  SURGSIM_ASSERT(t != nullptr) << "Null pointers sent in t variable";
78 
79  auto u = (s0v1 - s0v0).eval();
80  auto v = (s1v1 - s1v0).eval();
81  T denom = u[0] * v[1] - u[1] * v[0];
82  if (std::abs(denom) <= static_cast<T>(DistanceEpsilon))
83  {
84  return false;
85  }
86 
87  auto w = (s0v0 - s1v0).eval();
88  *s = (v[0] * w[1] - v[1] * w[0]) / denom;
89  *t = (u[0] * w[1] - u[1] * w[0]) / denom;
90 
91  return *s > -DistanceEpsilon && *s < (1.0 + DistanceEpsilon) &&
92  *t > -DistanceEpsilon && *t < (1.0 + DistanceEpsilon);
93 }
94 
104 template <class T, int MOpt> inline
105 bool barycentricCoordinates(const Eigen::Matrix<T, 3, 1, MOpt>& pt,
106  const Eigen::Matrix<T, 3, 1, MOpt>& sv0,
107  const Eigen::Matrix<T, 3, 1, MOpt>& sv1,
108  Eigen::Matrix<T, 2, 1, MOpt>* coordinates)
109 {
110  const Eigen::Matrix<T, 3, 1, MOpt> line = sv1 - sv0;
111  const T length2 = line.squaredNorm();
112  if (length2 < Geometry::SquaredDistanceEpsilon)
113  {
114  coordinates->setConstant((std::numeric_limits<double>::quiet_NaN()));
115  return false;
116  }
117  (*coordinates)[1] = (pt - sv0).dot(line) / length2;
118  (*coordinates)[0] = static_cast<T>(1) - (*coordinates)[1];
119  return true;
120 }
121 
132 template <class T, int MOpt> inline
133 bool barycentricCoordinates(const Eigen::Matrix<T, 3, 1, MOpt>& pt,
134  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
135  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
136  const Eigen::Matrix<T, 3, 1, MOpt>& tv2,
137  const Eigen::Matrix<T, 3, 1, MOpt>& tn,
138  Eigen::Matrix<T, 3, 1, MOpt>* coordinates)
139 {
140  const T signedTriAreaX2 = ((tv1 - tv0).cross(tv2 - tv0)).dot(tn);
141  if (signedTriAreaX2 < Geometry::SquaredDistanceEpsilon)
142  {
143  // SQ_ASSERT_WARNING(false, "Cannot compute barycentric coords (degenetrate triangle), assigning center");
144  coordinates->setConstant((std::numeric_limits<double>::quiet_NaN()));
145  return false;
146  }
147  (*coordinates)[0] = ((tv1 - pt).cross(tv2 - pt)).dot(tn) / signedTriAreaX2;
148  (*coordinates)[1] = ((tv2 - pt).cross(tv0 - pt)).dot(tn) / signedTriAreaX2;
149  (*coordinates)[2] = 1 - (*coordinates)[0] - (*coordinates)[1];
150  return true;
151 }
152 
163 template <class T, int MOpt> inline
165  const Eigen::Matrix<T, 3, 1, MOpt>& pt,
166  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
167  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
168  const Eigen::Matrix<T, 3, 1, MOpt>& tv2,
169  Eigen::Matrix<T, 3, 1, MOpt>* coordinates)
170 {
171  Eigen::Matrix<T, 3, 1, MOpt> tn = (tv1 - tv0).cross(tv2 - tv0);
172  double norm = tn.norm();
173  if (norm < Geometry::DistanceEpsilon)
174  {
175  coordinates->setConstant((std::numeric_limits<double>::quiet_NaN()));
176  return false;
177  }
178  tn /= norm;
179  return barycentricCoordinates(pt, tv0, tv1, tv2, tn, coordinates);
180 }
181 
192 template <class T, int MOpt> inline
194  const Eigen::Matrix<T, 3, 1, MOpt>& pt,
195  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
196  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
197  const Eigen::Matrix<T, 3, 1, MOpt>& tv2,
198  const Eigen::Matrix<T, 3, 1, MOpt>& tn)
199 {
200  Eigen::Matrix<T, 3, 1, MOpt> baryCoords;
201  return (barycentricCoordinates(pt, tv0, tv1, tv2, tn, &baryCoords) &&
202  baryCoords[0] * (tv0 - (tv2 * static_cast<T>(0.5) + tv1 * static_cast<T>(0.5))).norm() >=
203  -Geometry::ScalarEpsilon &&
204  baryCoords[1] * (tv1 - (tv0 * static_cast<T>(0.5) + tv2 * static_cast<T>(0.5))).norm() >=
205  -Geometry::ScalarEpsilon &&
206  baryCoords[2] * (tv2 - (tv1 * static_cast<T>(0.5) + tv0 * static_cast<T>(0.5))).norm() >=
207  -Geometry::ScalarEpsilon);
208 }
209 
219 template <class T, int MOpt> inline
221  const Eigen::Matrix<T, 3, 1, MOpt>& pt,
222  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
223  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
224  const Eigen::Matrix<T, 3, 1, MOpt>& tv2)
225 {
226  Eigen::Matrix<T, 3, 1, MOpt> baryCoords;
227  bool result = barycentricCoordinates(pt, tv0, tv1, tv2, &baryCoords);
228  return (result &&
229  baryCoords[0] * (tv0 - (tv2 * static_cast<T>(0.5) + tv1 * static_cast<T>(0.5))).norm() >=
230  -Geometry::ScalarEpsilon &&
231  baryCoords[1] * (tv1 - (tv0 * static_cast<T>(0.5) + tv2 * static_cast<T>(0.5))).norm() >=
232  -Geometry::ScalarEpsilon &&
233  baryCoords[2] * (tv2 - (tv1 * static_cast<T>(0.5) + tv0 * static_cast<T>(0.5))).norm() >=
234  -Geometry::ScalarEpsilon);
235 }
236 
242 template <class T, int MOpt> inline
244  const Eigen::Matrix<T, 3, 1, MOpt>& a,
245  const Eigen::Matrix<T, 3, 1, MOpt>& b,
246  const Eigen::Matrix<T, 3, 1, MOpt>& c,
247  const Eigen::Matrix<T, 3, 1, MOpt>& d)
248 {
249  return std::abs((c - a).dot((b - a).cross(d - c))) < Geometry::ScalarEpsilon;
250 }
251 
257 template <class T, int MOpt> inline
259  const Eigen::Matrix<T, 3, 1, MOpt>& pt,
260  const Eigen::Matrix<T, 3, 1, MOpt>& v0,
261  const Eigen::Matrix<T, 3, 1, MOpt>& v1,
262  Eigen::Matrix<T, 3, 1, MOpt>* result)
263 {
264  // The lines is parametrized by:
265  // q = v0 + lambda0 * (v1-v0)
266  // and we solve for pq.v01 = 0;
267  Eigen::Matrix<T, 3, 1, MOpt> v01 = v1 - v0;
268  T v01_norm2 = v01.squaredNorm();
269  if (v01_norm2 <= Geometry::SquaredDistanceEpsilon)
270  {
271  *result = v0; // closest point is either
272  T pv_norm2 = (pt - v0).squaredNorm();
273  return sqrt(pv_norm2);
274  }
275  T lambda = (v01).dot(pt - v0);
276  *result = v0 + lambda * v01 / v01_norm2;
277  return (*result - pt).norm();
278 }
279 
288 template <class T, int MOpt> inline
290  const Eigen::Matrix<T, 3, 1, MOpt>& pt,
291  const Eigen::Matrix<T, 3, 1, MOpt>& sv0,
292  const Eigen::Matrix<T, 3, 1, MOpt>& sv1,
293  Eigen::Matrix<T, 3, 1, MOpt>* result)
294 {
295  Eigen::Matrix<T, 3, 1, MOpt> v01 = sv1 - sv0;
296  T v01Norm2 = v01.squaredNorm();
297  if (v01Norm2 <= Geometry::SquaredDistanceEpsilon)
298  {
299  *result = sv0; // closest point is either
300  return (pt - sv0).norm();
301  }
302  T lambda = v01.dot(pt - sv0);
303  if (lambda <= 0)
304  {
305  *result = sv0;
306  }
307  else if (lambda >= v01Norm2)
308  {
309  *result = sv1;
310  }
311  else
312  {
313  *result = sv0 + lambda * v01 / v01Norm2;
314  }
315  return (*result - pt).norm();
316 }
317 
324 template <class T, int MOpt> inline
326  const Eigen::Matrix<T, 3, 1, MOpt>& pt,
327  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
328  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
329  const Eigen::Matrix<T, 3, 1, MOpt>& tv2)
330 {
331  Eigen::Matrix<T, 3, 1, MOpt> pointOnSegment;
332  return (distancePointSegment(pt, tv0, tv1, &pointOnSegment) < Geometry::ScalarEpsilon) ||
333  (distancePointSegment(pt, tv1, tv2, &pointOnSegment) < Geometry::ScalarEpsilon) ||
334  (distancePointSegment(pt, tv2, tv0, &pointOnSegment) < Geometry::ScalarEpsilon);
335 }
336 
347 template <class T, int MOpt> inline
349  const Eigen::Matrix<T, 3, 1, MOpt>& l0v0,
350  const Eigen::Matrix<T, 3, 1, MOpt>& l0v1,
351  const Eigen::Matrix<T, 3, 1, MOpt>& l1v0,
352  const Eigen::Matrix<T, 3, 1, MOpt>& l1v1,
353  Eigen::Matrix<T, 3, 1, MOpt>* pt0,
354  Eigen::Matrix<T, 3, 1, MOpt>* pt1)
355 {
356  // Based on the outline of http://www.geometrictools.com/Distance.html, also refer to
357  // http://geomalgorithms.com/a07-_distance.html for a geometric interpretation
358  // The lines are parametrized by:
359  // p0 = l0v0 + lambda0 * (l0v1-l0v0)
360  // p1 = l1v0 + lambda1 * (l1v1-l1v0)
361  // and we solve for p0p1 perpendicular to both lines
362  T lambda0, lambda1;
363  Eigen::Matrix<T, 3, 1, MOpt> l0v01 = l0v1 - l0v0;
364  T a = l0v01.squaredNorm();
365  if (a <= Geometry::SquaredDistanceEpsilon)
366  {
367  // Degenerate line 0
368  *pt0 = l0v0;
369  return distancePointSegment(l0v0, l1v0, l1v1, pt1);
370  }
371  Eigen::Matrix<T, 3, 1, MOpt> l1v01 = l1v1 - l1v0;
372  T b = -l0v01.dot(l1v01);
373  T c = l1v01.squaredNorm();
374  if (c <= Geometry::SquaredDistanceEpsilon)
375  {
376  // Degenerate line 1
377  *pt1 = l1v0;
378  return distancePointSegment(l1v0, l0v0, l0v1, pt0);
379  }
380  Eigen::Matrix<T, 3, 1, MOpt> l0v0_l1v0 = l0v0 - l1v0;
381  T d = l0v01.dot(l0v0_l1v0);
382  T e = -l1v01.dot(l0v0_l1v0);
383  T ratio = a * c - b * b;
384  if (std::abs(ratio) <= Geometry::ScalarEpsilon)
385  {
386  // parallel case
387  lambda0 = 0;
388  lambda1 = e / c;
389  }
390  else
391  {
392  // non-parallel case
393  T inv_ratio = T(1) / ratio;
394  lambda0 = (b * e - c * d) * inv_ratio;
395  lambda1 = (b * d - a * e) * inv_ratio;
396  }
397  *pt0 = l0v0 + lambda0 * l0v01;
398  *pt1 = l1v0 + lambda1 * l1v01;
399  return ((*pt0) - (*pt1)).norm();
400 }
401 
402 
414 template <class T, int MOpt>
416  const Eigen::Matrix<T, 3, 1, MOpt>& s0v0,
417  const Eigen::Matrix<T, 3, 1, MOpt>& s0v1,
418  const Eigen::Matrix<T, 3, 1, MOpt>& s1v0,
419  const Eigen::Matrix<T, 3, 1, MOpt>& s1v1,
420  Eigen::Matrix<T, 3, 1, MOpt>* pt0,
421  Eigen::Matrix<T, 3, 1, MOpt>* pt1,
422  T* s0t = nullptr,
423  T* s1t = nullptr)
424 {
425  // Based on the outline of http://www.geometrictools.com/Documentation/DistanceLine3Line3.pdf, also refer to
426  // http://geomalgorithms.com/a07-_distance.html for a geometric interpretation
427  // The segments are parametrized by:
428  // p0 = l0v0 + s * (l0v1-l0v0), with s between 0 and 1
429  // p1 = l1v0 + t * (l1v1-l1v0), with t between 0 and 1
430  // We are minimizing Q(s, t) = as*as + 2bst + ct*ct + 2ds + 2et + f,
431  Eigen::Matrix<T, 3, 1, MOpt> s0v01 = s0v1 - s0v0;
432  T a = s0v01.squaredNorm();
433  if (a <= Geometry::SquaredDistanceEpsilon)
434  {
435  // Degenerate segment 0
436  *pt0 = s0v0;
437  return distancePointSegment<T>(s0v0, s1v0, s1v1, pt1);
438  }
439  Eigen::Matrix<T, 3, 1, MOpt> s1v01 = s1v1 - s1v0;
440  T b = -s0v01.dot(s1v01);
441  T c = s1v01.squaredNorm();
442  if (c <= Geometry::SquaredDistanceEpsilon)
443  {
444  // Degenerate segment 1
445  *pt1 = s1v1;
446  return distancePointSegment<T>(s1v0, s0v0, s0v1, pt0);
447  }
448  Eigen::Matrix<T, 3, 1, MOpt> tempLine = s0v0 - s1v0;
449  T d = s0v01.dot(tempLine);
450  T e = -s1v01.dot(tempLine);
451  T ratio = a * c - b * b;
452  T s, t; // parametrization variables (do not initialize)
453  int region = -1;
454  T tmp;
455  // Non-parallel case
456  if (1.0 - std::abs(s0v01.normalized().dot(s1v01.normalized())) >= Geometry::SquaredDistanceEpsilon)
457  {
458  // Get the region of the global minimum in the s-t space based on the line-line solution
459  // s=0 s=1
460  // ^
461  // | |
462  // 4 | 3 | 2
463  // ----|-------|------- t=1
464  // | |
465  // 5 | 0 | 1
466  // | |
467  // ----|-------|-------> t=0
468  // | |
469  // 6 | 7 | 8
470  // | |
471  //
472  s = b * e - c * d;
473  t = b * d - a * e;
474  if (s >= 0)
475  {
476  if (s <= ratio)
477  {
478  if (t >= 0)
479  {
480  if (t <= ratio)
481  {
482  region = 0;
483  }
484  else
485  {
486  region = 3;
487  }
488  }
489  else
490  {
491  region = 7;
492  }
493  }
494  else
495  {
496  if (t >= 0)
497  {
498  if (t <= ratio)
499  {
500  region = 1;
501  }
502  else
503  {
504  region = 2;
505  }
506  }
507  else
508  {
509  region = 8;
510  }
511  }
512  }
513  else
514  {
515  if (t >= 0)
516  {
517  if (t <= ratio)
518  {
519  region = 5;
520  }
521  else
522  {
523  region = 4;
524  }
525  }
526  else
527  {
528  region = 6;
529  }
530  }
531  enum edge_type { s0, s1, t0, t1, edge_skip, edge_invalid };
532  edge_type edge = edge_invalid;
533  switch (region)
534  {
535  case 0:
536  // Global minimum inside [0,1] [0,1]
537  s /= ratio;
538  t /= ratio;
539  edge = edge_skip;
540  break;
541  case 1:
542  edge = s1;
543  break;
544  case 2:
545  // Q_s(1,1)/2 = a+b+d
546  if (a + b + d > 0)
547  {
548  edge = t1;
549  }
550  else
551  {
552  edge = s1;
553  }
554  break;
555  case 3:
556  edge = t1;
557  break;
558  case 4:
559  // Q_s(0,1)/2 = b+d
560  if (b + d > 0)
561  {
562  edge = s0;
563  }
564  else
565  {
566  edge = t1;
567  }
568  break;
569  case 5:
570  edge = s0;
571  break;
572  case 6:
573  // Q_s(0,0)/2 = d
574  if (d > 0)
575  {
576  edge = s0;
577  }
578  else
579  {
580  edge = t0;
581  }
582  break;
583  case 7:
584  edge = t0;
585  break;
586  case 8:
587  // Q_s(1,0)/2 = a+d
588  if (a + d > 0)
589  {
590  edge = t0;
591  }
592  else
593  {
594  edge = s1;
595  }
596  break;
597  default:
598  break;
599  }
600  switch (edge)
601  {
602  case s0:
603  // F(t) = Q(0,t), F?(t) = 2*(e+c*t)
604  // F?(T) = 0 when T = -e/c, then clamp between 0 and 1 (c always >= 0)
605  s = 0;
606  tmp = e;
607  if (tmp > 0)
608  {
609  t = 0;
610  }
611  else if (-tmp > c)
612  {
613  t = 1;
614  }
615  else
616  {
617  t = -tmp / c;
618  }
619  break;
620  case s1:
621  // F(t) = Q(1,t), F?(t) = 2*((b+e)+c*t)
622  // F?(T) = 0 when T = -(b+e)/c, then clamp between 0 and 1 (c always >= 0)
623  s = 1;
624  tmp = b + e;
625  if (tmp > 0)
626  {
627  t = 0;
628  }
629  else if (-tmp > c)
630  {
631  t = 1;
632  }
633  else
634  {
635  t = -tmp / c;
636  }
637  break;
638  case t0:
639  // F(s) = Q(s,0), F?(s) = 2*(d+a*s) =>
640  // F?(S) = 0 when S = -d/a, then clamp between 0 and 1 (a always >= 0)
641  t = 0;
642  tmp = d;
643  if (tmp > 0)
644  {
645  s = 0;
646  }
647  else if (-tmp > a)
648  {
649  s = 1;
650  }
651  else
652  {
653  s = -tmp / a;
654  }
655  break;
656  case t1:
657  // F(s) = Q(s,1), F?(s) = 2*(b+d+a*s) =>
658  // F?(S) = 0 when S = -(b+d)/a, then clamp between 0 and 1 (a always >= 0)
659  t = 1;
660  tmp = b + d;
661  if (tmp > 0)
662  {
663  s = 0;
664  }
665  else if (-tmp > a)
666  {
667  s = 1;
668  }
669  else
670  {
671  s = -tmp / a;
672  }
673  break;
674  case edge_skip:
675  break;
676  default:
677  break;
678  }
679  }
680  else
681  // Parallel case
682  {
683  if (b > 0)
684  {
685  // Segments have different directions
686  if (d >= 0)
687  {
688  // 0-0 end points since s-segment 0 less than t-segment 0
689  s = 0;
690  t = 0;
691  }
692  else if (-d <= a)
693  {
694  // s-segment 0 end-point in the middle of the t 0-1 segment, get distance
695  s = -d / a;
696  t = 0;
697  }
698  else
699  {
700  // s-segment 1 is definitely closer
701  s = 1;
702  tmp = a + d;
703  if (-tmp >= b)
704  {
705  t = 1;
706  }
707  else
708  {
709  t = -tmp / b;
710  }
711  }
712  }
713  else
714  {
715  // Both segments have the same dir
716  if (-d >= a)
717  {
718  // 1-0
719  s = 1;
720  t = 0;
721  }
722  else if (d <= 0)
723  {
724  // mid-0
725  s = -d / a;
726  t = 0;
727  }
728  else
729  {
730  s = 0;
731  // 1-mid
732  if (d >= -b)
733  {
734  t = 1;
735  }
736  else
737  {
738  t = -d / b;
739  }
740  }
741  }
742  }
743  *pt0 = s0v0 + s * (s0v01);
744  *pt1 = s1v0 + t * (s1v01);
745  if (s0t != nullptr && s1t != nullptr)
746  {
747  *s0t = s;
748  *s1t = t;
749  }
750  return ((*pt1) - (*pt0)).norm();
751 }
752 
762 template <class T, int MOpt> inline
764  const Eigen::Matrix<T, 3, 1, MOpt>& pt,
765  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
766  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
767  const Eigen::Matrix<T, 3, 1, MOpt>& tv2,
768  Eigen::Matrix<T, 3, 1, MOpt>* result)
769 {
770  // Based on the outline of http://www.geometrictools.com/Distance.html, also refer to
771  // http://softsurfer.com/Archive/algorithm_0106 for a geometric interpretation
772  // The triangle is parametrized by:
773  // t: tv0 + s * (tv1-tv0) + t * (tv2-tv0) , with s and t between 0 and 1
774  // We are minimizing Q(s, t) = as*as + 2bst + ct*ct + 2ds + 2et + f,
775  Eigen::Matrix<T, 3, 1, MOpt> tv01 = tv1 - tv0;
776  Eigen::Matrix<T, 3, 1, MOpt> tv02 = tv2 - tv0;
777  T a = tv01.squaredNorm();
778  if (a <= Geometry::SquaredDistanceEpsilon)
779  {
780  // Degenerate edge 1
781  return distancePointSegment<T>(pt, tv0, tv2, result);
782  }
783  T b = tv01.dot(tv02);
784  T tCross = tv01.cross(tv02).squaredNorm();
785  if (tCross <= Geometry::SquaredDistanceEpsilon)
786  {
787  // Degenerate edge 2
788  return distancePointSegment<T>(pt, tv0, tv1, result);
789  }
790  T c = tv02.squaredNorm();
791  if (c <= Geometry::SquaredDistanceEpsilon)
792  {
793  // Degenerate edge 3
794  return distancePointSegment<T>(pt, tv0, tv1, result);
795  }
796  Eigen::Matrix<T, 3, 1, MOpt> tv0pv0 = tv0 - pt;
797  T d = tv01.dot(tv0pv0);
798  T e = tv02.dot(tv0pv0);
799  T ratio = a * c - b * b;
800  T s = b * e - c * d;
801  T t = b * d - a * e;
802  // Determine region (inside-outside triangle)
803  int region = -1;
804  if (s + t <= ratio)
805  {
806  if (s < 0)
807  {
808  if (t < 0)
809  {
810  region = 4;
811  }
812  else
813  {
814  region = 3;
815  }
816  }
817  else if (t < 0)
818  {
819  region = 5;
820  }
821  else
822  {
823  region = 0;
824  }
825  }
826  else
827  {
828  if (s < 0)
829  {
830  region = 2;
831  }
832  else if (t < 0)
833  {
834  region = 6;
835  }
836  else
837  {
838  region = 1;
839  }
840  }
841  // Regions: /
842  // ^ t=0 /
843  // \ 2| /
844  // \ | /
845  // \| /
846  // \ /
847  // |\ /
848  // | \ 1 /
849  // 3 | \ /
850  // | 0 \ /
851  // ----|----\-------> s=0 /
852  // | \ /
853  // 4 | 5 \ 6 /
854  // | \ /
855  // /
856  T numer, denom, tmp0, tmp1;
857  enum edge_type { s0, t0, s1t1, edge_skip, edge_invalid };
858  edge_type edge = edge_invalid;
859  switch (region)
860  {
861  case 0:
862  // Global minimum inside [0,1] [0,1]
863  numer = T(1) / ratio;
864  s *= numer;
865  t *= numer;
866  edge = edge_skip;
867  break;
868  case 1:
869  edge = s1t1;
870  break;
871  case 2:
872  // Grad(Q(0,1)).(0,-1)/2 = -c-e
873  // Grad(Q(0,1)).(1,-1)/2 = b=d-c-e
874  tmp0 = b + d;
875  tmp1 = c + e;
876  if (tmp1 > tmp0)
877  {
878  edge = s1t1;
879  }
880  else
881  {
882  edge = s0;
883  }
884  break;
885  case 3:
886  edge = s0;
887  break;
888  case 4:
889  // Grad(Q(0,0)).(0,1)/2 = e
890  // Grad(Q(0,0)).(1,0)/2 = d
891  if (e >= d)
892  {
893  edge = t0;
894  }
895  else
896  {
897  edge = s0;
898  }
899  break;
900  case 5:
901  edge = t0;
902  break;
903  case 6:
904  // Grad(Q(1,0)).(-1,0)/2 = -a-d
905  // Grad(Q(1,0)).(-1,1)/2 = -a-d+b+e
906  tmp0 = -a - d;
907  tmp1 = -a - d + b + e;
908  if (tmp1 > tmp0)
909  {
910  edge = t0;
911  }
912  else
913  {
914  edge = s1t1;
915  }
916  break;
917  default:
918  break;
919  }
920  switch (edge)
921  {
922  case s0:
923  // F(t) = Q(0, t), F'(t)=0 when -e/c = 0
924  s = 0;
925  if (e >= 0)
926  {
927  t = 0;
928  }
929  else
930  {
931  t = (-e >= c ? 1 : -e / c);
932  }
933  break;
934  case t0:
935  // F(s) = Q(s, 0), F'(s)=0 when -d/a = 0
936  t = 0;
937  if (d >= 0)
938  {
939  s = 0;
940  }
941  else
942  {
943  s = (-d >= a ? 1 : -d / a);
944  }
945  break;
946  case s1t1:
947  // F(s) = Q(s, 1-s), F'(s) = 0 when (c+e-b-d)/(a-2b+c) = 0 (denom = || tv01-tv02 ||^2 always > 0)
948  numer = c + e - b - d;
949  if (numer <= 0)
950  {
951  s = 0;
952  }
953  else
954  {
955  denom = a - 2 * b + c;
956  s = (numer >= denom ? 1 : numer / denom);
957  }
958  t = 1 - s;
959  break;
960  case edge_skip:
961  break;
962  default:
963  break;
964  }
965  *result = tv0 + s * tv01 + t * tv02;
966  return ((*result) - pt).norm();
967 }
968 
983 template <class T, int MOpt> inline
985  const Eigen::Matrix<T, 3, 1, MOpt>& sv0,
986  const Eigen::Matrix<T, 3, 1, MOpt>& sv1,
987  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
988  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
989  const Eigen::Matrix<T, 3, 1, MOpt>& tv2,
990  const Eigen::Matrix<T, 3, 1, MOpt>& tn,
991  Eigen::Matrix<T, 3, 1, MOpt>* result)
992 {
993  // Triangle edges vectors
994  Eigen::Matrix<T, 3, 1, MOpt> u = tv1 - tv0;
995  Eigen::Matrix<T, 3, 1, MOpt> v = tv2 - tv0;
996 
997  // Ray direction vector
998  Eigen::Matrix<T, 3, 1, MOpt> dir = sv1 - sv0;
999  Eigen::Matrix<T, 3, 1, MOpt> w0 = sv0 - tv0;
1000  T a = -tn.dot(w0);
1001  T b = tn.dot(dir);
1002 
1003  result->setConstant((std::numeric_limits<double>::quiet_NaN()));
1004 
1005  // Ray is parallel to triangle plane
1006  if (std::abs(b) <= Geometry::AngularEpsilon)
1007  {
1008  if (std::abs(a) <= Geometry::AngularEpsilon)
1009  {
1010  // Ray lies in triangle plane
1011  Eigen::Matrix<T, 3, 1, MOpt> baryCoords;
1012  for (int i = 0; i < 2; ++i)
1013  {
1014  barycentricCoordinates((i == 0 ? sv0 : sv1), tv0, tv1, tv2, tn, &baryCoords);
1015  if (baryCoords[0] >= 0 && baryCoords[1] >= 0 && baryCoords[2] >= 0)
1016  {
1017  *result = (i == 0) ? sv0 : sv1;
1018  return true;
1019  }
1020  }
1021  // All segment endpoints outside of triangle
1022  return false;
1023  }
1024  else
1025  {
1026  // Segment parallel to triangle but not in same plane
1027  return false;
1028  }
1029  }
1030 
1031  // Get intersect point of ray with triangle plane
1032  T r = a / b;
1033  // Ray goes away from triangle
1034  if (r < -Geometry::DistanceEpsilon)
1035  {
1036  return false;
1037  }
1038  //Ray comes toward triangle but isn't long enough to reach it
1039  if (r > 1 + Geometry::DistanceEpsilon)
1040  {
1041  return false;
1042  }
1043 
1044  // Intersect point of ray and plane
1045  Eigen::Matrix<T, 3, 1, MOpt> presumedIntersection = sv0 + r * dir;
1046  // Collision point inside T?
1047  T uu = u.dot(u);
1048  T uv = u.dot(v);
1049  T vv = v.dot(v);
1050  Eigen::Matrix<T, 3, 1, MOpt> w = presumedIntersection - tv0;
1051  T wu = w.dot(u);
1052  T wv = w.dot(v);
1053  T D = uv * uv - uu * vv;
1054  // Get and test parametric coords
1055  T s = (uv * wv - vv * wu) / D;
1056  // I is outside T
1057  if (s < -Geometry::DistanceEpsilon || s > 1 + Geometry::DistanceEpsilon)
1058  {
1059  return false;
1060  }
1061  T t = (uv * wu - uu * wv) / D;
1062  // I is outside T
1063  if (t < -Geometry::DistanceEpsilon || (s + t) > 1 + Geometry::DistanceEpsilon)
1064  {
1065  return false;
1066  }
1067  // I is in T
1068  *result = sv0 + r * dir;
1069  return true;
1070 }
1071 
1072 
1082 template <class T, int MOpt> inline
1084  const Eigen::Matrix<T, 3, 1, MOpt>& pt,
1085  const Eigen::Matrix<T, 3, 1, MOpt>& n,
1086  T d,
1087  Eigen::Matrix<T, 3, 1, MOpt>* result)
1088 {
1089  T dist = n.dot(pt) + d;
1090  *result = pt - n * dist;
1091  return dist;
1092 }
1093 
1094 
1109 template <class T, int MOpt> inline
1111  const Eigen::Matrix<T, 3, 1, MOpt>& sv0,
1112  const Eigen::Matrix<T, 3, 1, MOpt>& sv1,
1113  const Eigen::Matrix<T, 3, 1, MOpt>& n,
1114  T d,
1115  Eigen::Matrix<T, 3, 1, MOpt>* closestPointSegment,
1116  Eigen::Matrix<T, 3, 1, MOpt>* planeIntersectionPoint)
1117 {
1118  T dist0 = n.dot(sv0) + d;
1119  T dist1 = n.dot(sv1) + d;
1120  // Parallel case
1121  Eigen::Matrix<T, 3, 1, MOpt> v01 = sv1 - sv0;
1122  if (std::abs(n.dot(v01)) <= Geometry::AngularEpsilon)
1123  {
1124  *closestPointSegment = (sv0 + sv1) * T(0.5);
1125  dist0 = n.dot(*closestPointSegment) + d;
1126  *planeIntersectionPoint = *closestPointSegment - dist0 * n;
1127  return (std::abs(dist0) < Geometry::DistanceEpsilon ? 0 : dist0);
1128  }
1129  // Both on the same side
1130  if ((dist0 > 0 && dist1 > 0) || (dist0 < 0 && dist1 < 0))
1131  {
1132  if (std::abs(dist0) < std::abs(dist1))
1133  {
1134  *closestPointSegment = sv0;
1135  *planeIntersectionPoint = sv0 - dist0 * n;
1136  return dist0;
1137  }
1138  else
1139  {
1140  *closestPointSegment = sv1;
1141  *planeIntersectionPoint = sv1 - dist1 * n;
1142  return dist1;
1143  }
1144  }
1145  // Segment cutting through
1146  else
1147  {
1148  Eigen::Matrix<T, 3, 1, MOpt> v01 = sv1 - sv0;
1149  T lambda = (-d - sv0.dot(n)) / v01.dot(n);
1150  *planeIntersectionPoint = sv0 + lambda * v01;
1151  *closestPointSegment = *planeIntersectionPoint;
1152  return 0;
1153  }
1154 }
1155 
1165 template <class T, int MOpt> inline
1167  const Eigen::Matrix<T, 3, 1, MOpt>& v0,
1168  const Eigen::Matrix<T, 3, 1, MOpt>& v1,
1169  const Eigen::Matrix<T, 3, 1, MOpt>& n,
1170  T d,
1171  Eigen::Matrix<T, 3, 1, MOpt>* intersectionPoint)
1172 {
1173  Eigen::Matrix<T, 3, 1, MOpt> v01 = v1 - v0;
1174  T v01dotN = v01.dot(n);
1175  if (std::abs(n.dot(v01.normalized())) > Geometry::AngularEpsilon)
1176  {
1177  T lambda = (-d - v0.dot(n)) / v01dotN;
1178  *intersectionPoint = v0 + lambda * v01;
1179  return 0;
1180  }
1181  T dist = std::abs(v0.dot(n) + d);
1182  if (dist < Geometry::DistanceEpsilon)
1183  {
1184  *intersectionPoint = v0;
1185  return 0;
1186  }
1187  return dist;
1188 }
1189 
1203 template <class T, int MOpt> inline
1205  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
1206  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
1207  const Eigen::Matrix<T, 3, 1, MOpt>& tv2,
1208  const Eigen::Matrix<T, 3, 1, MOpt>& n,
1209  T d,
1210  Eigen::Matrix<T, 3, 1, MOpt>* closestPointTriangle,
1211  Eigen::Matrix<T, 3, 1, MOpt>* planeProjectionPoint)
1212 {
1213  Eigen::Matrix<T, 3, 1, MOpt> distances(n.dot(tv0) + d, n.dot(tv1) + d, n.dot(tv2) + d);
1214  Eigen::Matrix<T, 3, 1, MOpt> t01 = tv1 - tv0;
1215  Eigen::Matrix<T, 3, 1, MOpt> t02 = tv2 - tv0;
1216  Eigen::Matrix<T, 3, 1, MOpt> t12 = tv2 - tv1;
1217 
1218  closestPointTriangle->setConstant((std::numeric_limits<double>::quiet_NaN()));
1219  planeProjectionPoint->setConstant((std::numeric_limits<double>::quiet_NaN()));
1220 
1221  // HS-2013-may-09 Could there be a case where we fall into the wrong tree because of the checks against
1222  // the various epsilon values all going against us ???
1223  // Parallel case (including Coplanar)
1224  if (std::abs(n.dot(t01)) <= Geometry::AngularEpsilon && std::abs(n.dot(t02)) <= Geometry::AngularEpsilon)
1225  {
1226  *closestPointTriangle = (tv0 + tv1 + tv2) / T(3);
1227  *planeProjectionPoint = *closestPointTriangle - n * distances[0];
1228  return distances[0];
1229  }
1230 
1231  // Is there an intersection
1232  if ((distances.array() < -Geometry::DistanceEpsilon).any() &&
1233  (distances.array() > Geometry::DistanceEpsilon).any())
1234  {
1235  if (distances[0] * distances[1] < 0)
1236  {
1237  *closestPointTriangle = tv0 + (-d - n.dot(tv0)) / n.dot(t01) * t01;
1238  if (distances[0] * distances[2] < 0)
1239  {
1240  *planeProjectionPoint = tv0 + (-d - n.dot(tv0)) / n.dot(t02) * t02;
1241  }
1242  else
1243  {
1244  Eigen::Matrix<T, 3, 1, MOpt> t12 = tv2 - tv1;
1245  *planeProjectionPoint = tv1 + (-d - n.dot(tv1)) / n.dot(t12) * t12;
1246  }
1247  }
1248  else
1249  {
1250  *closestPointTriangle = tv0 + (-d - n.dot(tv0)) / n.dot(t02) * t02;
1251  *planeProjectionPoint = tv1 + (-d - n.dot(tv1)) / n.dot(t12) * t12;
1252  }
1253 
1254  // Find the midpoint, take this out to return the segment endpoints
1255  *closestPointTriangle = *planeProjectionPoint = (*closestPointTriangle + *planeProjectionPoint) * T(0.5);
1256  return 0;
1257  }
1258 
1259  int index;
1260  distances.cwiseAbs().minCoeff(&index);
1261  switch (index)
1262  {
1263  case 0: //distances[0] is closest
1264  *closestPointTriangle = tv0;
1265  *planeProjectionPoint = tv0 - n * distances[0];
1266  return distances[0];
1267  case 1: //distances[1] is closest
1268  *closestPointTriangle = tv1;
1269  *planeProjectionPoint = tv1 - n * distances[1];
1270  return distances[1];
1271  case 2: //distances[2] is closest
1272  *closestPointTriangle = tv2;
1273  *planeProjectionPoint = tv2 - n * distances[2];
1274  return distances[2];
1275  }
1276 
1277  return std::numeric_limits<T>::quiet_NaN();
1278 }
1279 
1287 template <class T, int MOpt> inline
1289  const Eigen::Matrix<T, 3, 1, MOpt>& pn0, T pd0,
1290  const Eigen::Matrix<T, 3, 1, MOpt>& pn1, T pd1,
1291  Eigen::Matrix<T, 3, 1, MOpt>* pt0,
1292  Eigen::Matrix<T, 3, 1, MOpt>* pt1)
1293 {
1294  // Algorithm from real time collision detection - optimized version page 210 (with extra checks)
1295  const Eigen::Matrix<T, 3, 1, MOpt> lineDir = pn0.cross(pn1);
1296  const T lineDirNorm2 = lineDir.squaredNorm();
1297 
1298  pt0->setConstant((std::numeric_limits<double>::quiet_NaN()));
1299  pt1->setConstant((std::numeric_limits<double>::quiet_NaN()));
1300 
1301  // Test if the two planes are parallel
1302  if (lineDirNorm2 <= Geometry::SquaredDistanceEpsilon)
1303  {
1304  return false; // planes disjoint
1305  }
1306  // Compute common point
1307  *pt0 = (pd1 * pn0 - pd0 * pn1).cross(lineDir) / lineDirNorm2;
1308  *pt1 = *pt0 + lineDir;
1309  return true;
1310 }
1311 
1322 template <class T, int MOpt> inline
1324  const Eigen::Matrix<T, 3, 1, MOpt>& sv0,
1325  const Eigen::Matrix<T, 3, 1, MOpt>& sv1,
1326  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
1327  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
1328  const Eigen::Matrix<T, 3, 1, MOpt>& tv2,
1329  const Eigen::Matrix<T, 3, 1, MOpt>& normal,
1330  Eigen::Matrix<T, 3, 1, MOpt>* segmentPoint,
1331  Eigen::Matrix<T, 3, 1, MOpt>* trianglePoint)
1332 {
1333  segmentPoint->setConstant((std::numeric_limits<double>::quiet_NaN()));
1334  trianglePoint->setConstant((std::numeric_limits<double>::quiet_NaN()));
1335 
1336  // Setting up the plane that the triangle is in
1337  const Eigen::Matrix<T, 3, 1, MOpt>& n = normal;
1338  T d = -n.dot(tv0);
1339  Eigen::Matrix<T, 3, 1, MOpt> baryCoords;
1340  // Degenerate case: Line and triangle plane parallel
1341  const Eigen::Matrix<T, 3, 1, MOpt> v01 = sv1 - sv0;
1342  const T v01DotTn = n.dot(v01);
1343  if (std::abs(n.dot(v01.normalized())) <= Geometry::AngularEpsilon)
1344  {
1345  // Check if any of the points project onto the tri
1346  // otherwise normal (non-parallel) processing will get the right result
1347  T dst = std::abs(distancePointPlane(sv0, n, d, trianglePoint));
1348  Eigen::Matrix<T, 3, 1, MOpt> baryCoords;
1349  barycentricCoordinates(*trianglePoint, tv0, tv1, tv2, normal, &baryCoords);
1350  if (baryCoords[0] >= 0 && baryCoords[1] >= 0 && baryCoords[2] >= 0)
1351  {
1352  *segmentPoint = sv0;
1353  return dst;
1354  }
1355  dst = std::abs(distancePointPlane(sv1, n, d, trianglePoint));
1356  barycentricCoordinates(*trianglePoint, tv0, tv1, tv2, normal, &baryCoords);
1357  if (baryCoords[0] >= 0 && baryCoords[1] >= 0 && baryCoords[2] >= 0)
1358  {
1359  *segmentPoint = sv1;
1360  return dst;
1361  }
1362  }
1363  // Line and triangle plane *not* parallel: check cut through case only, the rest will be check later
1364  else
1365  {
1366  T lambda = -n.dot(sv0 - tv0) / v01DotTn;
1367  if (lambda >= 0 && lambda <= 1)
1368  {
1369  *segmentPoint = *trianglePoint = sv0 + lambda * v01;
1370  if (isPointInsideTriangle(*trianglePoint, tv0, tv1, tv2, normal))
1371  {
1372  // Segment goes through the triangle
1373  return 0;
1374  }
1375  }
1376  }
1377  // At this point the segment is nearest point to one of the triangle edges or one of the end points
1378  Eigen::Matrix<T, 3, 1, MOpt> segColPt01, segColPt02, segColPt12, triColPt01, triColPt02, triColPt12;
1379  T dst01 = distanceSegmentSegment(sv0, sv1, tv0, tv1, &segColPt01, &triColPt01);
1380  T dst02 = distanceSegmentSegment(sv0, sv1, tv0, tv2, &segColPt02, &triColPt02);
1381  T dst12 = distanceSegmentSegment(sv0, sv1, tv1, tv2, &segColPt12, &triColPt12);
1382  Eigen::Matrix<T, 3, 1, MOpt> ptTriCol0, ptTriCol1;
1383  T dstPtTri0 = std::abs(distancePointPlane(sv0, n, d, &ptTriCol0));
1384  if (!isPointInsideTriangle(ptTriCol0, tv0, tv1, tv2, normal))
1385  {
1386  dstPtTri0 = std::numeric_limits<T>::max();
1387  }
1388  T dstPtTri1 = std::abs(distancePointPlane(sv1, n, d, &ptTriCol1));
1389  if (!isPointInsideTriangle(ptTriCol1, tv0, tv1, tv2, normal))
1390  {
1391  dstPtTri1 = std::numeric_limits<T>::max();
1392  }
1393 
1394  int minIndex;
1395  Eigen::Matrix<double, 5, 1> distances;
1396  (distances << dst01, dst02, dst12, dstPtTri0, dstPtTri1).finished().minCoeff(&minIndex);
1397  switch (minIndex)
1398  {
1399  case 0:
1400  *segmentPoint = segColPt01;
1401  *trianglePoint = triColPt01;
1402  return dst01;
1403  case 1:
1404  *segmentPoint = segColPt02;
1405  *trianglePoint = triColPt02;
1406  return dst02;
1407  case 2:
1408  *segmentPoint = segColPt12;
1409  *trianglePoint = triColPt12;
1410  return dst12;
1411  case 3:
1412  *segmentPoint = sv0;
1413  *trianglePoint = ptTriCol0;
1414  return dstPtTri0;
1415  case 4:
1416  *segmentPoint = sv1;
1417  *trianglePoint = ptTriCol1;
1418  return dstPtTri1;
1419  }
1420 
1421  // Invalid ...
1422  return std::numeric_limits<T>::quiet_NaN();
1423 
1424 }
1425 
1426 
1437 template <class T, int MOpt> inline
1439  const Eigen::Matrix<T, 3, 1, MOpt>& sv0,
1440  const Eigen::Matrix<T, 3, 1, MOpt>& sv1,
1441  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
1442  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
1443  const Eigen::Matrix<T, 3, 1, MOpt>& tv2,
1444  Eigen::Matrix<T, 3, 1, MOpt>* segmentPoint,
1445  Eigen::Matrix<T, 3, 1, MOpt>* trianglePoint)
1446 {
1447  Eigen::Matrix<T, 3, 1, MOpt> n = (tv1 - tv0).cross(tv2 - tv1);
1448  n.normalize();
1449  return distanceSegmentTriangle(sv0, sv1, tv0, tv1, tv2, n, segmentPoint, trianglePoint);
1450 }
1451 
1462 template <class T, int MOpt> inline
1464  const Eigen::Matrix<T, 3, 1, MOpt>& t0v0,
1465  const Eigen::Matrix<T, 3, 1, MOpt>& t0v1,
1466  const Eigen::Matrix<T, 3, 1, MOpt>& t0v2,
1467  const Eigen::Matrix<T, 3, 1, MOpt>& t1v0,
1468  const Eigen::Matrix<T, 3, 1, MOpt>& t1v1,
1469  const Eigen::Matrix<T, 3, 1, MOpt>& t1v2,
1470  Eigen::Matrix<T, 3, 1, MOpt>* closestPoint0,
1471  Eigen::Matrix<T, 3, 1, MOpt>* closestPoint1)
1472 {
1473  // Check the segments of t0 against t1
1474  T minDst = std::numeric_limits<T>::max();
1475  T currDst = 0;
1476  Eigen::Matrix<T, 3, 1, MOpt> segPt, triPt;
1477  Eigen::Matrix<T, 3, 1, MOpt> n0 = (t0v1 - t0v0).cross(t0v2 - t0v0);
1478  n0.normalize();
1479  Eigen::Matrix<T, 3, 1, MOpt> n1 = (t1v1 - t1v0).cross(t1v2 - t1v0);
1480  n1.normalize();
1481  currDst = distanceSegmentTriangle(t0v0, t0v1, t1v0, t1v1, t1v2, n1, &segPt, &triPt);
1482  if (currDst < minDst)
1483  {
1484  minDst = currDst;
1485  *closestPoint0 = segPt;
1486  *closestPoint1 = triPt;
1487  }
1488  currDst = distanceSegmentTriangle(t0v1, t0v2, t1v0, t1v1, t1v2, n1, &segPt, &triPt);
1489  if (currDst < minDst)
1490  {
1491  minDst = currDst;
1492  *closestPoint0 = segPt;
1493  *closestPoint1 = triPt;
1494  }
1495  currDst = distanceSegmentTriangle(t0v2, t0v0, t1v0, t1v1, t1v2, n1, &segPt, &triPt);
1496  if (currDst < minDst)
1497  {
1498  minDst = currDst;
1499  *closestPoint0 = segPt;
1500  *closestPoint1 = triPt;
1501  }
1502  // Check the segments of t1 against t0
1503  currDst = distanceSegmentTriangle(t1v0, t1v1, t0v0, t0v1, t0v2, n0, &segPt, &triPt);
1504  if (currDst < minDst)
1505  {
1506  minDst = currDst;
1507  *closestPoint1 = segPt;
1508  *closestPoint0 = triPt;
1509  }
1510  currDst = distanceSegmentTriangle(t1v1, t1v2, t0v0, t0v1, t0v2, n0, &segPt, &triPt);
1511  if (currDst < minDst)
1512  {
1513  minDst = currDst;
1514  *closestPoint1 = segPt;
1515  *closestPoint0 = triPt;
1516  }
1517  currDst = distanceSegmentTriangle(t1v2, t1v0, t0v0, t0v1, t0v2, n0, &segPt, &triPt);
1518  if (currDst < minDst)
1519  {
1520  minDst = currDst;
1521  *closestPoint1 = segPt;
1522  *closestPoint0 = triPt;
1523  }
1524  return (minDst);
1525 }
1526 
1533 template <class T, int MOpt>
1535  const Eigen::Matrix<T, 3, 1, MOpt>& sv0,
1536  const Eigen::Matrix<T, 3, 1, MOpt>& sv1,
1537  const Eigen::AlignedBox<T, 3>& box,
1538  std::vector<Eigen::Matrix<T, 3, 1, MOpt>>* intersections)
1539 {
1540  Eigen::Array<T, 3, 1, MOpt> v01 = sv1 - sv0;
1541  Eigen::Array<bool, 3, 1, MOpt> parallelToPlane = (v01.cwiseAbs().array() < Geometry::DistanceEpsilon);
1542  if (parallelToPlane.any())
1543  {
1544  Eigen::Array<bool, 3, 1, MOpt> beyondMinCorner = (sv0.array() < box.min().array());
1545  Eigen::Array<bool, 3, 1, MOpt> beyondMaxCorner = (sv0.array() > box.max().array());
1546  if ((parallelToPlane && (beyondMinCorner || beyondMaxCorner)).any())
1547  {
1548  return;
1549  }
1550  }
1551 
1552  // Calculate the intersection of the segment with each of the 6 box planes.
1553  // The intersection is calculated as the distance along the segment (abscissa)
1554  // scaled from 0 to 1.
1555  Eigen::Array<T, 3, 2, MOpt> planeIntersectionAbscissas;
1556  planeIntersectionAbscissas.col(0) = (box.min().array() - sv0.array());
1557  planeIntersectionAbscissas.col(1) = (box.max().array() - sv0.array());
1558 
1559  // While we could be dividing by zero here, INF values are
1560  // correctly handled by the rest of the function.
1561  planeIntersectionAbscissas.colwise() /= v01;
1562 
1563  T entranceAbscissa = planeIntersectionAbscissas.rowwise().minCoeff().maxCoeff();
1564  T exitAbscissa = planeIntersectionAbscissas.rowwise().maxCoeff().minCoeff();
1565  if (entranceAbscissa < exitAbscissa && exitAbscissa > T(0.0))
1566  {
1567  if (entranceAbscissa >= T(0.0) && entranceAbscissa <= T(1.0))
1568  {
1569  intersections->push_back(sv0 + v01.matrix() * entranceAbscissa);
1570  }
1571 
1572  if (exitAbscissa >= T(0.0) && exitAbscissa <= T(1.0))
1573  {
1574  intersections->push_back(sv0 + v01.matrix() * exitAbscissa);
1575  }
1576  }
1577 }
1578 
1587 template <class T, int MOpt>
1589  const Eigen::Matrix<T, 3, 1, MOpt>& capsuleBottom,
1590  const Eigen::Matrix<T, 3, 1, MOpt>& capsuleTop,
1591  const T capsuleRadius,
1592  const Eigen::AlignedBox<T, 3>& box)
1593 {
1594  Eigen::AlignedBox<double, 3> dilatedBox(box.min().array() - capsuleRadius, box.max().array() + capsuleRadius);
1595  std::vector<Vector3d> candidates;
1596  intersectionsSegmentBox(capsuleBottom, capsuleTop, dilatedBox, &candidates);
1597  if (dilatedBox.contains(capsuleBottom))
1598  {
1599  candidates.push_back(capsuleBottom);
1600  }
1601  if (dilatedBox.contains(capsuleTop))
1602  {
1603  candidates.push_back(capsuleTop);
1604  }
1605 
1606  bool doesIntersect = false;
1607  ptrdiff_t dimensionsOutsideBox;
1608  Vector3d clampedPosition, segmentPoint;
1609  for (auto candidate = candidates.cbegin(); candidate != candidates.cend(); ++candidate)
1610  {
1611  // Collisions between a capsule and a box are the same as a segment and a dilated
1612  // box with rounded corners. If the intersection occurs outside the original box
1613  // in two dimensions (collision with an edge of the dilated box) or three
1614  // dimensions (collision with the corner of the dilated box) dimensions, we need
1615  // to check if it is inside these rounded corners.
1616  dimensionsOutsideBox = (candidate->array() > box.max().array()).count();
1617  dimensionsOutsideBox += (candidate->array() < box.min().array()).count();
1618  if (dimensionsOutsideBox >= 2)
1619  {
1620  clampedPosition = (*candidate).array().min(box.max().array()).max(box.min().array());
1621  if (distancePointSegment(clampedPosition, capsuleBottom, capsuleTop, &segmentPoint) > capsuleRadius)
1622  {
1623  // Doesn't intersect, try the next candidate.
1624  continue;
1625  }
1626  }
1627  doesIntersect = true;
1628  break;
1629  }
1630  return doesIntersect;
1631 }
1632 
1640 template <class T, int VOpt>
1641 Eigen::Matrix<T, 3, 1, VOpt> nearestPointOnLine(const Eigen::Matrix<T, 3, 1, VOpt>& point,
1642  const Eigen::Matrix<T, 3, 1, VOpt>& segment0, const Eigen::Matrix<T, 3, 1, VOpt>& segment1)
1643 {
1644  auto pointToSegmentStart = segment0 - point;
1645  auto segmentDirection = segment1 - segment0;
1646  auto squaredNorm = segmentDirection.squaredNorm();
1647  SURGSIM_ASSERT(squaredNorm != 0.0) << "Line is defined by two collocated points.";
1648  auto distance = -pointToSegmentStart.dot(segmentDirection) / squaredNorm;
1649  auto p0Proj = segment0 + distance * segmentDirection;
1650  return p0Proj;
1651 }
1652 
1663 template <class T, int MOpt> inline
1665  const Eigen::Matrix<T, 3, 1, MOpt>& t0v0,
1666  const Eigen::Matrix<T, 3, 1, MOpt>& t0v1,
1667  const Eigen::Matrix<T, 3, 1, MOpt>& t0v2,
1668  const Eigen::Matrix<T, 3, 1, MOpt>& t1v0,
1669  const Eigen::Matrix<T, 3, 1, MOpt>& t1v1,
1670  const Eigen::Matrix<T, 3, 1, MOpt>& t1v2,
1671  const Eigen::Matrix<T, 3, 1, MOpt>& t0n,
1672  const Eigen::Matrix<T, 3, 1, MOpt>& t1n);
1673 
1680 template <class T, int MOpt> inline
1681 bool doesIntersectTriangleTriangle(
1682  const Eigen::Matrix<T, 3, 1, MOpt>& t0v0,
1683  const Eigen::Matrix<T, 3, 1, MOpt>& t0v1,
1684  const Eigen::Matrix<T, 3, 1, MOpt>& t0v2,
1685  const Eigen::Matrix<T, 3, 1, MOpt>& t1v0,
1686  const Eigen::Matrix<T, 3, 1, MOpt>& t1v1,
1687  const Eigen::Matrix<T, 3, 1, MOpt>& t1v2);
1688 
1708 template <class T, int MOpt> inline
1710  const Eigen::Matrix<T, 3, 1, MOpt>& t0v0,
1711  const Eigen::Matrix<T, 3, 1, MOpt>& t0v1,
1712  const Eigen::Matrix<T, 3, 1, MOpt>& t0v2,
1713  const Eigen::Matrix<T, 3, 1, MOpt>& t1v0,
1714  const Eigen::Matrix<T, 3, 1, MOpt>& t1v1,
1715  const Eigen::Matrix<T, 3, 1, MOpt>& t1v2,
1716  const Eigen::Matrix<T, 3, 1, MOpt>& t0n,
1717  const Eigen::Matrix<T, 3, 1, MOpt>& t1n,
1718  T* penetrationDepth,
1719  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPoint0,
1720  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPoint1,
1721  Eigen::Matrix<T, 3, 1, MOpt>* contactNormal);
1722 
1740 template <class T, int MOpt> inline
1741 bool calculateContactTriangleTriangle(
1742  const Eigen::Matrix<T, 3, 1, MOpt>& t0v0,
1743  const Eigen::Matrix<T, 3, 1, MOpt>& t0v1,
1744  const Eigen::Matrix<T, 3, 1, MOpt>& t0v2,
1745  const Eigen::Matrix<T, 3, 1, MOpt>& t1v0,
1746  const Eigen::Matrix<T, 3, 1, MOpt>& t1v1,
1747  const Eigen::Matrix<T, 3, 1, MOpt>& t1v2,
1748  T* penetrationDepth,
1749  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPoint0,
1750  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPoint1,
1751  Eigen::Matrix<T, 3, 1, MOpt>* contactNormal);
1752 
1770 template <class T, int MOpt> inline
1772  const Eigen::Matrix<T, 3, 1, MOpt>& t0v0,
1773  const Eigen::Matrix<T, 3, 1, MOpt>& t0v1,
1774  const Eigen::Matrix<T, 3, 1, MOpt>& t0v2,
1775  const Eigen::Matrix<T, 3, 1, MOpt>& t1v0,
1776  const Eigen::Matrix<T, 3, 1, MOpt>& t1v1,
1777  const Eigen::Matrix<T, 3, 1, MOpt>& t1v2,
1778  const Eigen::Matrix<T, 3, 1, MOpt>& t0n,
1779  const Eigen::Matrix<T, 3, 1, MOpt>& t1n,
1780  T* penetrationDepth,
1781  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPoint0,
1782  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPoint1,
1783  Eigen::Matrix<T, 3, 1, MOpt>* contactNormal);
1784 
1798 template <class T, int MOpt> inline
1799 bool calculateContactTriangleTriangleSeparatingAxis(
1800  const Eigen::Matrix<T, 3, 1, MOpt>& t0v0,
1801  const Eigen::Matrix<T, 3, 1, MOpt>& t0v1,
1802  const Eigen::Matrix<T, 3, 1, MOpt>& t0v2,
1803  const Eigen::Matrix<T, 3, 1, MOpt>& t1v0,
1804  const Eigen::Matrix<T, 3, 1, MOpt>& t1v1,
1805  const Eigen::Matrix<T, 3, 1, MOpt>& t1v2,
1806  T* penetrationDepth,
1807  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPoint0,
1808  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPoint1,
1809  Eigen::Matrix<T, 3, 1, MOpt>* contactNormal);
1810 
1828 template <class T, int MOpt> inline
1830  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
1831  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
1832  const Eigen::Matrix<T, 3, 1, MOpt>& tv2,
1833  const Eigen::Matrix<T, 3, 1, MOpt>& tn,
1834  const Eigen::Matrix<T, 3, 1, MOpt>& cv0,
1835  const Eigen::Matrix<T, 3, 1, MOpt>& cv1,
1836  double cr,
1837  T* penetrationDepth,
1838  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPointTriangle,
1839  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPointCapsule,
1840  Eigen::Matrix<T, 3, 1, MOpt>* contactNormal,
1841  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPointCapsuleAxis);
1842 
1859 template <class T, int MOpt> inline
1860 bool calculateContactTriangleCapsule(
1861  const Eigen::Matrix<T, 3, 1, MOpt>& tv0,
1862  const Eigen::Matrix<T, 3, 1, MOpt>& tv1,
1863  const Eigen::Matrix<T, 3, 1, MOpt>& tv2,
1864  const Eigen::Matrix<T, 3, 1, MOpt>& cv0,
1865  const Eigen::Matrix<T, 3, 1, MOpt>& cv1,
1866  double cr,
1867  T* penetrationDepth,
1868  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPointTriangle,
1869  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPointCapsule,
1870  Eigen::Matrix<T, 3, 1, MOpt>* contactNormal,
1871  Eigen::Matrix<T, 3, 1, MOpt>* penetrationPointCapsuleAxis);
1872 
1879 template <class T, int MOpt>
1881  const std::pair<Eigen::Matrix<T, 3, 1, MOpt>, Eigen::Matrix<T, 3, 1, MOpt>>& A,
1882  const std::pair<Eigen::Matrix<T, 3, 1, MOpt>, Eigen::Matrix<T, 3, 1, MOpt>>& B,
1883  const std::pair<Eigen::Matrix<T, 3, 1, MOpt>, Eigen::Matrix<T, 3, 1, MOpt>>& C,
1884  const std::pair<Eigen::Matrix<T, 3, 1, MOpt>, Eigen::Matrix<T, 3, 1, MOpt>>& D,
1885  std::array<T, 3>* timesOfCoplanarity)
1886 {
1902  Eigen::Matrix<T, 3, 1, MOpt> AB0 = B.first - A.first;
1903  Eigen::Matrix<T, 3, 1, MOpt> AC0 = C.first - A.first;
1904  Eigen::Matrix<T, 3, 1, MOpt> CD0 = D.first - C.first;
1905  Eigen::Matrix<T, 3, 1, MOpt> VA = (A.second - A.first);
1906  Eigen::Matrix<T, 3, 1, MOpt> VC = (C.second - C.first);
1907  Eigen::Matrix<T, 3, 1, MOpt> VAB = (B.second - B.first) - VA;
1908  Eigen::Matrix<T, 3, 1, MOpt> VAC = VC - VA;
1909  Eigen::Matrix<T, 3, 1, MOpt> VCD = (D.second - D.first) - VC;
1910  T a0 = AB0.cross(CD0).dot(AC0);
1911  T a1 = AB0.cross(CD0).dot(VAC) + (AB0.cross(VCD) + VAB.cross(CD0)).dot(AC0);
1912  T a2 = (AB0.cross(VCD) + VAB.cross(CD0)).dot(VAC) + VAB.cross(VCD).dot(AC0);
1913  T a3 = VAB.cross(VCD).dot(VAC);
1914 
1915  return findRootsInRange01(Polynomial<T, 3>(a0, a1, a2, a3), timesOfCoplanarity);
1916 }
1917 
1918 }; // namespace Math
1919 }; // namespace SurgSim
1920 
1921 
1922 #include "SurgSim/Math/PointTriangleCcdContactCalculation-inl.h"
1923 #include "SurgSim/Math/SegmentSegmentCcdContactCalculation-inl.h"
1924 #include "SurgSim/Math/TriangleCapsuleContactCalculation-inl.h"
1925 #include "SurgSim/Math/TriangleTriangleIntersection-inl.h"
1926 #include "SurgSim/Math/TriangleTriangleContactCalculation-inl.h"
1927 
1928 #endif
T distancePointSegment(const Eigen::Matrix< T, 3, 1, MOpt > &pt, const Eigen::Matrix< T, 3, 1, MOpt > &sv0, const Eigen::Matrix< T, 3, 1, MOpt > &sv1, Eigen::Matrix< T, 3, 1, MOpt > *result)
Point segment distance, if the projection of the closest point is not within the segments, the closest segment point is used for the distance calculation.
Definition: Geometry.h:289
Wraps glewInit() to separate the glew opengl definitions from the osg opengl definitions only imgui n...
Definition: AddRandomSphereBehavior.cpp:36
int timesOfCoplanarityInRange01(const std::pair< Eigen::Matrix< T, 3, 1, MOpt >, Eigen::Matrix< T, 3, 1, MOpt >> &A, const std::pair< Eigen::Matrix< T, 3, 1, MOpt >, Eigen::Matrix< T, 3, 1, MOpt >> &B, const std::pair< Eigen::Matrix< T, 3, 1, MOpt >, Eigen::Matrix< T, 3, 1, MOpt >> &C, const std::pair< Eigen::Matrix< T, 3, 1, MOpt >, Eigen::Matrix< T, 3, 1, MOpt >> &D, std::array< T, 3 > *timesOfCoplanarity)
Test when 4 points are coplanar in the range [0..1] given their linear motion.
Definition: Geometry.h:1880
T distanceTrianglePlane(const Eigen::Matrix< T, 3, 1, MOpt > &tv0, const Eigen::Matrix< T, 3, 1, MOpt > &tv1, const Eigen::Matrix< T, 3, 1, MOpt > &tv2, const Eigen::Matrix< T, 3, 1, MOpt > &n, T d, Eigen::Matrix< T, 3, 1, MOpt > *closestPointTriangle, Eigen::Matrix< T, 3, 1, MOpt > *planeProjectionPoint)
Calculate the distance of a triangle to a plane.
Definition: Geometry.h:1204
bool isCoplanar(const Eigen::Matrix< T, 3, 1, MOpt > &a, const Eigen::Matrix< T, 3, 1, MOpt > &b, const Eigen::Matrix< T, 3, 1, MOpt > &c, const Eigen::Matrix< T, 3, 1, MOpt > &d)
Check whether the points are coplanar.
Definition: Geometry.h:243
bool doesIntersectPlanePlane(const Eigen::Matrix< T, 3, 1, MOpt > &pn0, T pd0, const Eigen::Matrix< T, 3, 1, MOpt > &pn1, T pd1, Eigen::Matrix< T, 3, 1, MOpt > *pt0, Eigen::Matrix< T, 3, 1, MOpt > *pt1)
Test if two planes are intersecting, if yes also calculate the intersection line. ...
Definition: Geometry.h:1288
bool calculateContactTriangleCapsule(const Eigen::Matrix< T, 3, 1, MOpt > &tv0, const Eigen::Matrix< T, 3, 1, MOpt > &tv1, const Eigen::Matrix< T, 3, 1, MOpt > &tv2, const Eigen::Matrix< T, 3, 1, MOpt > &tn, const Eigen::Matrix< T, 3, 1, MOpt > &cv0, const Eigen::Matrix< T, 3, 1, MOpt > &cv1, double cr, T *penetrationDepth, Eigen::Matrix< T, 3, 1, MOpt > *penetrationPointTriangle, Eigen::Matrix< T, 3, 1, MOpt > *penetrationPointCapsule, Eigen::Matrix< T, 3, 1, MOpt > *contactNormal, Eigen::Matrix< T, 3, 1, MOpt > *penetrationPointCapsuleAxis)
Calculate the contact between a capsule and a triangle.
Definition: TriangleCapsuleContactCalculation-inl.h:920
bool calculateContactTriangleTriangleSeparatingAxis(const Eigen::Matrix< T, 3, 1, MOpt > &t0v0, const Eigen::Matrix< T, 3, 1, MOpt > &t0v1, const Eigen::Matrix< T, 3, 1, MOpt > &t0v2, const Eigen::Matrix< T, 3, 1, MOpt > &t1v0, const Eigen::Matrix< T, 3, 1, MOpt > &t1v1, const Eigen::Matrix< T, 3, 1, MOpt > &t1v2, const Eigen::Matrix< T, 3, 1, MOpt > &t0n, const Eigen::Matrix< T, 3, 1, MOpt > &t1n, T *penetrationDepth, Eigen::Matrix< T, 3, 1, MOpt > *penetrationPoint0, Eigen::Matrix< T, 3, 1, MOpt > *penetrationPoint1, Eigen::Matrix< T, 3, 1, MOpt > *contactNormal)
Calculate the contact between two triangles.
Definition: TriangleTriangleContactCalculation-inl.h:302
#define SURGSIM_ASSERT(condition)
Assert that condition is true.
Definition: Assert.h:77
T distanceTriangleTriangle(const Eigen::Matrix< T, 3, 1, MOpt > &t0v0, const Eigen::Matrix< T, 3, 1, MOpt > &t0v1, const Eigen::Matrix< T, 3, 1, MOpt > &t0v2, const Eigen::Matrix< T, 3, 1, MOpt > &t1v0, const Eigen::Matrix< T, 3, 1, MOpt > &t1v1, const Eigen::Matrix< T, 3, 1, MOpt > &t1v2, Eigen::Matrix< T, 3, 1, MOpt > *closestPoint0, Eigen::Matrix< T, 3, 1, MOpt > *closestPoint1)
Calculate the distance between two triangles.
Definition: Geometry.h:1463
Eigen::Matrix< double, 3, 1 > Vector3d
A 3D vector of doubles.
Definition: Vector.h:57
T distanceSegmentTriangle(const Eigen::Matrix< T, 3, 1, MOpt > &sv0, const Eigen::Matrix< T, 3, 1, MOpt > &sv1, const Eigen::Matrix< T, 3, 1, MOpt > &tv0, const Eigen::Matrix< T, 3, 1, MOpt > &tv1, const Eigen::Matrix< T, 3, 1, MOpt > &tv2, const Eigen::Matrix< T, 3, 1, MOpt > &normal, Eigen::Matrix< T, 3, 1, MOpt > *segmentPoint, Eigen::Matrix< T, 3, 1, MOpt > *trianglePoint)
Calculate the distance of a line segment to a triangle.
Definition: Geometry.h:1323
Eigen::Matrix< T, 3, 1, VOpt > nearestPointOnLine(const Eigen::Matrix< T, 3, 1, VOpt > &point, const Eigen::Matrix< T, 3, 1, VOpt > &segment0, const Eigen::Matrix< T, 3, 1, VOpt > &segment1)
Helper method to determine the nearest point between a point and a line.
Definition: Geometry.h:1641
The convenience header that provides the entirety of the logging API.
Polynomial<T, 3> specializes the Polynomial class for degree 3 (cubic polynomials) ...
Definition: Polynomial.h:255
bool barycentricCoordinates(const Eigen::Matrix< T, 3, 1, MOpt > &pt, const Eigen::Matrix< T, 3, 1, MOpt > &sv0, const Eigen::Matrix< T, 3, 1, MOpt > &sv1, Eigen::Matrix< T, 2, 1, MOpt > *coordinates)
Calculate the barycentric coordinates of a point with respect to a line segment.
Definition: Geometry.h:105
T distanceSegmentPlane(const Eigen::Matrix< T, 3, 1, MOpt > &sv0, const Eigen::Matrix< T, 3, 1, MOpt > &sv1, const Eigen::Matrix< T, 3, 1, MOpt > &n, T d, Eigen::Matrix< T, 3, 1, MOpt > *closestPointSegment, Eigen::Matrix< T, 3, 1, MOpt > *planeIntersectionPoint)
Calculate the distance between a segment and a plane.
Definition: Geometry.h:1110
T distancePointPlane(const Eigen::Matrix< T, 3, 1, MOpt > &pt, const Eigen::Matrix< T, 3, 1, MOpt > &n, T d, Eigen::Matrix< T, 3, 1, MOpt > *result)
Calculate the distance of a point to a plane.
Definition: Geometry.h:1083
bool doesIntersectTriangleTriangle(const Eigen::Matrix< T, 3, 1, MOpt > &t0v0, const Eigen::Matrix< T, 3, 1, MOpt > &t0v1, const Eigen::Matrix< T, 3, 1, MOpt > &t0v2, const Eigen::Matrix< T, 3, 1, MOpt > &t1v0, const Eigen::Matrix< T, 3, 1, MOpt > &t1v1, const Eigen::Matrix< T, 3, 1, MOpt > &t1v2, const Eigen::Matrix< T, 3, 1, MOpt > &t0n, const Eigen::Matrix< T, 3, 1, MOpt > &t1n)
Check if the two triangles intersect using separating axis test.
Definition: TriangleTriangleIntersection-inl.h:70
T distanceLinePlane(const Eigen::Matrix< T, 3, 1, MOpt > &v0, const Eigen::Matrix< T, 3, 1, MOpt > &v1, const Eigen::Matrix< T, 3, 1, MOpt > &n, T d, Eigen::Matrix< T, 3, 1, MOpt > *intersectionPoint)
Calculate the distance between a line and a plane.
Definition: Geometry.h:1166
bool doesCollideSegmentTriangle(const Eigen::Matrix< T, 3, 1, MOpt > &sv0, const Eigen::Matrix< T, 3, 1, MOpt > &sv1, const Eigen::Matrix< T, 3, 1, MOpt > &tv0, const Eigen::Matrix< T, 3, 1, MOpt > &tv1, const Eigen::Matrix< T, 3, 1, MOpt > &tv2, const Eigen::Matrix< T, 3, 1, MOpt > &tn, Eigen::Matrix< T, 3, 1, MOpt > *result)
Calculate the intersection of a line segment with a triangle See http://geomalgorithms.com/a06-_intersect-2.html#intersect_RayTriangle for the algorithm.
Definition: Geometry.h:984
bool calculateContactTriangleTriangle(const Eigen::Matrix< T, 3, 1, MOpt > &t0v0, const Eigen::Matrix< T, 3, 1, MOpt > &t0v1, const Eigen::Matrix< T, 3, 1, MOpt > &t0v2, const Eigen::Matrix< T, 3, 1, MOpt > &t1v0, const Eigen::Matrix< T, 3, 1, MOpt > &t1v1, const Eigen::Matrix< T, 3, 1, MOpt > &t1v2, const Eigen::Matrix< T, 3, 1, MOpt > &t0n, const Eigen::Matrix< T, 3, 1, MOpt > &t1n, T *penetrationDepth, Eigen::Matrix< T, 3, 1, MOpt > *penetrationPoint0, Eigen::Matrix< T, 3, 1, MOpt > *penetrationPoint1, Eigen::Matrix< T, 3, 1, MOpt > *contactNormal)
Calculate the contact between two triangles.
Definition: TriangleTriangleContactCalculation-inl.h:216
T distancePointLine(const Eigen::Matrix< T, 3, 1, MOpt > &pt, const Eigen::Matrix< T, 3, 1, MOpt > &v0, const Eigen::Matrix< T, 3, 1, MOpt > &v1, Eigen::Matrix< T, 3, 1, MOpt > *result)
Calculate the normal distance between a point and a line.
Definition: Geometry.h:258
T distancePointTriangle(const Eigen::Matrix< T, 3, 1, MOpt > &pt, const Eigen::Matrix< T, 3, 1, MOpt > &tv0, const Eigen::Matrix< T, 3, 1, MOpt > &tv1, const Eigen::Matrix< T, 3, 1, MOpt > &tv2, Eigen::Matrix< T, 3, 1, MOpt > *result)
Calculate the normal distance of a point from a triangle, the resulting point will be on the edge of ...
Definition: Geometry.h:763
bool doesIntersectBoxCapsule(const Eigen::Matrix< T, 3, 1, MOpt > &capsuleBottom, const Eigen::Matrix< T, 3, 1, MOpt > &capsuleTop, const T capsuleRadius, const Eigen::AlignedBox< T, 3 > &box)
Test if an axis aligned box intersects with a capsule.
Definition: Geometry.h:1588
Definitions of small fixed-size vector types.
bool isPointOnTriangleEdge(const Eigen::Matrix< T, 3, 1, MOpt > &pt, const Eigen::Matrix< T, 3, 1, MOpt > &tv0, const Eigen::Matrix< T, 3, 1, MOpt > &tv1, const Eigen::Matrix< T, 3, 1, MOpt > &tv2)
Check if a point is on the edge of a triangle.
Definition: Geometry.h:325
void intersectionsSegmentBox(const Eigen::Matrix< T, 3, 1, MOpt > &sv0, const Eigen::Matrix< T, 3, 1, MOpt > &sv1, const Eigen::AlignedBox< T, 3 > &box, std::vector< Eigen::Matrix< T, 3, 1, MOpt >> *intersections)
Calculate the intersections between a line segment and an axis aligned box.
Definition: Geometry.h:1534
T distanceSegmentSegment(const Eigen::Matrix< T, 3, 1, MOpt > &s0v0, const Eigen::Matrix< T, 3, 1, MOpt > &s0v1, const Eigen::Matrix< T, 3, 1, MOpt > &s1v0, const Eigen::Matrix< T, 3, 1, MOpt > &s1v1, Eigen::Matrix< T, 3, 1, MOpt > *pt0, Eigen::Matrix< T, 3, 1, MOpt > *pt1, T *s0t=nullptr, T *s1t=nullptr)
Distance between two segments, if the project of the closest point is not on the opposing segment...
Definition: Geometry.h:415
T distanceLineLine(const Eigen::Matrix< T, 3, 1, MOpt > &l0v0, const Eigen::Matrix< T, 3, 1, MOpt > &l0v1, const Eigen::Matrix< T, 3, 1, MOpt > &l1v0, const Eigen::Matrix< T, 3, 1, MOpt > &l1v1, Eigen::Matrix< T, 3, 1, MOpt > *pt0, Eigen::Matrix< T, 3, 1, MOpt > *pt1)
Determine the distance between two lines.
Definition: Geometry.h:348
bool isPointInsideTriangle(const Eigen::Matrix< T, 3, 1, MOpt > &pt, const Eigen::Matrix< T, 3, 1, MOpt > &tv0, const Eigen::Matrix< T, 3, 1, MOpt > &tv1, const Eigen::Matrix< T, 3, 1, MOpt > &tv2, const Eigen::Matrix< T, 3, 1, MOpt > &tn)
Check if a point projected into the plane of a triangle, is inside that triangle. ...
Definition: Geometry.h:193
bool doesIntersectSegmentSegment(const Eigen::Matrix< T, 2, 1, MOpt > &s0v0, const Eigen::Matrix< T, 2, 1, MOpt > &s0v1, const Eigen::Matrix< T, 2, 1, MOpt > &s1v0, const Eigen::Matrix< T, 2, 1, MOpt > &s1v1, T *s, T *t)
Calculate the intersection between the two 2D segments.
Definition: Geometry.h:68