GteDistLine3Rectangle3.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>, Rectangle3<Real>>
20 {
21 public:
22  struct Result
23  {
25  Real lineParameter, rectangleParameter[2];
26  Vector3<Real> closestPoint[2];
27  };
28 
29  Result operator()(Line3<Real> const& line,
30  Rectangle3<Real> const& rectangle);
31 };
32 
33 // Template alias for convenience.
34 template <typename Real>
35 using DCPLine3Rectangle3 =
37 
38 
39 template <typename Real>
40 typename DCPQuery<Real, Line3<Real>, Rectangle3<Real>>::Result
41 DCPQuery<Real, Line3<Real>, Rectangle3<Real>>::operator()(
42  Line3<Real> const& line, Rectangle3<Real> const& rectangle)
43 {
44  Result result;
45 
46  // Test if line intersects rectangle. If so, the squared distance is
47  // zero.
48  Vector3<Real> N = Cross(rectangle.axis[0], rectangle.axis[1]);
49  Real NdD = Dot(N, line.direction);
50  if (std::abs(NdD) > (Real)0)
51  {
52  // The line and rectangle are not parallel, so the line intersects
53  // the plane of the rectangle.
54  Vector3<Real> diff = line.origin - rectangle.center;
55  Vector3<Real> basis[3]; // {D, U, V}
56  basis[0] = line.direction;
57  ComputeOrthogonalComplement<Real>(1, basis);
58  Real UdD0 = Dot(basis[1], rectangle.axis[0]);
59  Real UdD1 = Dot(basis[1], rectangle.axis[1]);
60  Real UdPmC = Dot(basis[1], diff);
61  Real VdD0 = Dot(basis[2], rectangle.axis[0]);
62  Real VdD1 = Dot(basis[2], rectangle.axis[1]);
63  Real VdPmC = Dot(basis[2], diff);
64  Real invDet = ((Real)1) / (UdD0*VdD1 - UdD1*VdD0);
65 
66  // Rectangle coordinates for the point of intersection.
67  Real s0 = (VdD1*UdPmC - UdD1*VdPmC)*invDet;
68  Real s1 = (UdD0*VdPmC - VdD0*UdPmC)*invDet;
69 
70  if (std::abs(s0) <= rectangle.extent[0]
71  && std::abs(s1) <= rectangle.extent[1])
72  {
73  // Line parameter for the point of intersection.
74  Real DdD0 = Dot(line.direction, rectangle.axis[0]);
75  Real DdD1 = Dot(line.direction, rectangle.axis[1]);
76  Real DdDiff = Dot(line.direction, diff);
77  result.lineParameter = s0*DdD0 + s1*DdD1 - DdDiff;
78 
79  // Rectangle coordinates for the point of intersection.
80  result.rectangleParameter[0] = s0;
81  result.rectangleParameter[1] = s1;
82 
83  // The intersection point is inside or on the rectangle.
84  result.closestPoint[0] = line.origin +
85  result.lineParameter*line.direction;
86 
87  result.closestPoint[1] = rectangle.center +
88  s0*rectangle.axis[0] + s1*rectangle.axis[1];
89 
90  result.distance = (Real)0;
91  result.sqrDistance = (Real)0;
92  return result;
93  }
94  }
95 
96  // Either (1) the line is not parallel to the rectangle and the point of
97  // intersection of the line and the plane of the rectangle is outside the
98  // rectangle or (2) the line and rectangle are parallel. Regardless, the
99  // closest point on the rectangle is on an edge of the rectangle. Compare
100  // the line to all four edges of the rectangle.
101  result.distance = std::numeric_limits<Real>::max();
102  result.sqrDistance = std::numeric_limits<Real>::max();
103  Vector3<Real> scaledDir[2] =
104  {
105  rectangle.extent[0] * rectangle.axis[0],
106  rectangle.extent[1] * rectangle.axis[1]
107  };
108  for (int i1 = 0, omi1 = 1; i1 <= 1; ++i1, --omi1)
109  {
110  for (int i0 = -1; i0 <= 1; i0 += 2)
111  {
112  Vector3<Real> segCenter =
113  rectangle.center + scaledDir[i1] * (Real)i0;
114  Vector3<Real> segDirection = rectangle.axis[omi1];
115  Real segExtent = rectangle.extent[omi1];
116  Segment3<Real> segment(segCenter, segDirection, segExtent);
117 
119  auto lsResult = query(line, segment);
120  if (lsResult.sqrDistance < result.sqrDistance)
121  {
122  result.sqrDistance = lsResult.sqrDistance;
123  result.distance = lsResult.distance;
124  result.lineParameter = lsResult.parameter[0];
125  Real ratio = lsResult.parameter[1] / segExtent; // in [-1,1]
126  result.rectangleParameter[0] =
127  rectangle.extent[0] * (omi1 * i0 + i1 * ratio);
128  result.rectangleParameter[1] =
129  rectangle.extent[1] * (i1 * i0 + omi1 * ratio);
130  result.closestPoint[0] = lsResult.closestPoint[0];
131  result.closestPoint[1] = lsResult.closestPoint[1];
132  }
133  }
134  }
135 
136  return result;
137 }
138 
139 
140 }
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s0
Definition: glext.h:9013
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)
DualQuaternion< Real > Cross(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition: glext.h:9013
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