GteDistLine3Triangle3.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <Mathematics/GteVector3.h>
13 #include <limits>
14 
15 namespace gte
16 {
17 
18 template <typename Real>
19 class DCPQuery<Real, Line3<Real>, Triangle3<Real>>
20 {
21 public:
22  struct Result
23  {
25  Real lineParameter, triangleParameter[3];
26  Vector3<Real> closestPoint[2];
27  };
28 
29  Result operator()(Line3<Real> const& line,
30  Triangle3<Real> const& triangle);
31 };
32 
33 
34 template <typename Real>
37  Line3<Real> const& line, Triangle3<Real> const& triangle)
38 {
39  Result result;
40 
41  // Test if line intersects triangle. If so, the squared distance is zero.
42  Vector3<Real> edge0 = triangle.v[1] - triangle.v[0];
43  Vector3<Real> edge1 = triangle.v[2] - triangle.v[0];
44  Vector3<Real> normal = UnitCross(edge0, edge1);
45  Real NdD = Dot(normal, line.direction);
46  if (std::abs(NdD) > (Real)0)
47  {
48  // The line and triangle are not parallel, so the line intersects
49  // the plane of the triangle.
50  Vector3<Real> diff = line.origin - triangle.v[0];
51  Vector3<Real> basis[3]; // {D, U, V}
52  basis[0] = line.direction;
53  ComputeOrthogonalComplement<Real>(1, basis);
54  Real UdE0 = Dot(basis[1], edge0);
55  Real UdE1 = Dot(basis[1], edge1);
56  Real UdDiff = Dot(basis[1], diff);
57  Real VdE0 = Dot(basis[2], edge0);
58  Real VdE1 = Dot(basis[2], edge1);
59  Real VdDiff = Dot(basis[2], diff);
60  Real invDet = ((Real)1) / (UdE0*VdE1 - UdE1*VdE0);
61 
62  // Barycentric coordinates for the point of intersection.
63  Real b1 = (VdE1*UdDiff - UdE1*VdDiff)*invDet;
64  Real b2 = (UdE0*VdDiff - VdE0*UdDiff)*invDet;
65  Real b0 = (Real)1 - b1 - b2;
66 
67  if (b0 >= (Real)0 && b1 >= (Real)0 && b2 >= (Real)0)
68  {
69  // Line parameter for the point of intersection.
70  Real DdE0 = Dot(line.direction, edge0);
71  Real DdE1 = Dot(line.direction, edge1);
72  Real DdDiff = Dot(line.direction, diff);
73  result.lineParameter = b1*DdE0 + b2*DdE1 - DdDiff;
74 
75  // Barycentric coordinates for the point of intersection.
76  result.triangleParameter[0] = b0;
77  result.triangleParameter[1] = b1;
78  result.triangleParameter[2] = b2;
79 
80  // The intersection point is inside or on the triangle.
81  result.closestPoint[0] = line.origin +
82  result.lineParameter*line.direction;
83  result.closestPoint[1] = triangle.v[0] + b1*edge0 + b2*edge1;
84 
85  result.distance = (Real)0;
86  result.sqrDistance = (Real)0;
87  return result;
88  }
89  }
90 
91  // Either (1) the line is not parallel to the triangle and the point of
92  // intersection of the line and the plane of the triangle is outside the
93  // triangle or (2) the line and triangle are parallel. Regardless, the
94  // closest point on the triangle is on an edge of the triangle. Compare
95  // the line to all three edges of the triangle.
96  result.distance = std::numeric_limits<Real>::max();
97  result.sqrDistance = std::numeric_limits<Real>::max();
98  for (int i0 = 2, i1 = 0; i1 < 3; i0 = i1++)
99  {
100  Vector3<Real> segCenter = ((Real)0.5)*(triangle.v[i0] +
101  triangle.v[i1]);
102  Vector3<Real> segDirection = triangle.v[i1] - triangle.v[i0];
103  Real segExtent = ((Real)0.5)*Normalize(segDirection);
104  Segment3<Real> segment(segCenter, segDirection, segExtent);
105 
107  auto lsResult = query(line, segment);
108  if (lsResult.sqrDistance < result.sqrDistance)
109  {
110  result.sqrDistance = lsResult.sqrDistance;
111  result.distance = lsResult.distance;
112  result.lineParameter = lsResult.parameter[0];
113  result.triangleParameter[i0] = ((Real)0.5)*((Real)1 -
114  lsResult.parameter[0] / segExtent);
115  result.triangleParameter[i1] = (Real)1 -
116  result.triangleParameter[i0];
117  result.triangleParameter[3 - i0 - i1] = (Real)0;
118  result.closestPoint[0] = lsResult.closestPoint[0];
119  result.closestPoint[1] = lsResult.closestPoint[1];
120  }
121  }
122 
123  return result;
124 }
125 
126 
127 }
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
Vector< N, Real > UnitCross(Vector< N, Real > const &v0, Vector< N, Real > const &v1, bool robust=false)
Definition: GteVector3.h:130
GLsizei GLsizei GLfloat distance
Definition: glext.h:9704
Result operator()(Type0 const &primitive0, Type1 const &primitive1)
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
Real Normalize(GVector< Real > &v, bool robust=false)
Definition: GteGVector.h:454
GLuint64EXT * result
Definition: glext.h:10003
GLenum query
Definition: glext.h:2716


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 03:59:59