GteIntrSegment3Ellipsoid3.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 
11 #include <Mathematics/GteSegment.h>
14 
15 // The queries consider the ellipsoid to be a solid.
16 
17 namespace gte
18 {
19 
20 template <typename Real>
21 class TIQuery<Real, Segment3<Real>, Ellipsoid3<Real>>
22 {
23 public:
24  struct Result
25  {
26  bool intersect;
27  };
28 
29  Result operator()(Segment3<Real> const& segment,
30  Ellipsoid3<Real> const& ellipsoid);
31 };
32 
33 template <typename Real>
34 class FIQuery<Real, Segment3<Real>, Ellipsoid3<Real>>
35  :
36  public FIQuery<Real, Line3<Real>, Ellipsoid3<Real>>
37 {
38 public:
39  struct Result
40  :
41  public FIQuery<Real, Line3<Real>, Ellipsoid3<Real>>::Result
42  {
43  // No additional information to compute.
44  };
45 
46  Result operator()(Segment3<Real> const& segment,
47  Ellipsoid3<Real> const& ellipsoid);
48 
49 protected:
50  void DoQuery(Vector3<Real> const& segOrigin,
51  Vector3<Real> const& segDirection, Real segExtent,
52  Ellipsoid3<Real> const& ellipsoid, Result& result);
53 };
54 
55 
56 template <typename Real>
59  Segment3<Real> const& segment, Ellipsoid3<Real> const& ellipsoid)
60 {
61  // The ellipsoid is (X-K)^T*M*(X-K)-1 = 0 and the line is X = P+t*D.
62  // Substitute the line equation into the ellipsoid equation to obtain
63  // a quadratic equation Q(t) = a2*t^2 + 2*a1*t + a0 = 0, where
64  // a2 = D^T*M*D, a1 = D^T*M*(P-K), and a0 = (P-K)^T*M*(P-K)-1.
65  Result result;
66 
67  Vector3<Real> segOrigin, segDirection;
68  Real segExtent;
69  segment.GetCenteredForm(segOrigin, segDirection, segExtent);
70 
72  ellipsoid.GetM(M);
73 
74  Vector3<Real> diff = segOrigin - ellipsoid.center;
75  Vector3<Real> matDir = M*segDirection;
76  Vector3<Real> matDiff = M*diff;
77  Real a2 = Dot(segDirection, matDir);
78  Real a1 = Dot(segDirection, matDiff);
79  Real a0 = Dot(diff, matDiff) - (Real)1;
80 
81  Real discr = a1*a1 - a0*a2;
82  if (discr >= (Real)0)
83  {
84  // Test whether ray origin is inside ellipsoid.
85  if (a0 <= (Real)0)
86  {
87  result.intersect = true;
88  }
89  else
90  {
91  // At this point, Q(0) = a0 > 0 and Q(t) has real roots. It is
92  // also the case that a2 > 0, since M is positive definite,
93  // implying that D^T*M*D > 0 for any nonzero vector D.
94  Real q, qder;
95  if (a1 >= (Real)0)
96  {
97  // Roots are possible only on [-e,0], e is the segment extent.
98  // At least one root occurs if Q(-e) <= 0 or if Q(-e) > 0 and
99  // Q'(-e) < 0.
100  q = a0 + segExtent*(((Real)-2)*a1 + a2*segExtent);
101  if (q <= (Real)0)
102  {
103  result.intersect = true;
104  }
105  else
106  {
107  qder = a1 - a2*segExtent;
108  result.intersect = (qder < (Real)0);
109  }
110  }
111  else
112  {
113  // Roots are only possible on [0,e], e is the segment extent.
114  // At least one root occurs if Q(e) <= 0 or if Q(e) > 0 and
115  // Q'(e) > 0.
116  q = a0 + segExtent*(((Real)2)*a1 + a2*segExtent);
117  if (q <= (Real)0.0)
118  {
119  result.intersect = true;
120  }
121  else
122  {
123  qder = a1 + a2*segExtent;
124  result.intersect = (qder < (Real)0);
125  }
126  }
127  }
128  }
129  else
130  {
131  // No intersection if Q(t) has no real roots.
132  result.intersect = false;
133  }
134 
135  return result;
136 }
137 
138 template <typename Real>
141  Segment3<Real> const& segment, Ellipsoid3<Real> const& ellipsoid)
142 {
143  Vector3<Real> segOrigin, segDirection;
144  Real segExtent;
145  segment.GetCenteredForm(segOrigin, segDirection, segExtent);
146 
147  Result result;
148  DoQuery(segOrigin, segDirection, segExtent, ellipsoid, result);
149  for (int i = 0; i < result.numIntersections; ++i)
150  {
151  result.point[i] = segOrigin + result.parameter[i] * segDirection;
152  }
153  return result;
154 }
155 
156 template <typename Real>
158  Vector3<Real> const& segOrigin, Vector3<Real> const& segDirection,
159  Real segExtent, Ellipsoid3<Real> const& ellipsoid, Result& result)
160 {
161  FIQuery<Real, Line3<Real>, Ellipsoid3<Real>>::DoQuery(segOrigin,
162  segDirection, ellipsoid, result);
163 
164  if (result.intersect)
165  {
166  // The line containing the segment intersects the ellipsoid; the
167  // t-interval is [t0,t1]. The segment intersects the ellipsoid as
168  // long as [t0,t1] overlaps the segment t-interval
169  // [-segExtent,+segExtent].
170  std::array<Real, 2> segInterval = { -segExtent, segExtent };
171  FIQuery<Real, std::array<Real, 2>, std::array<Real, 2>> iiQuery;
172  auto iiResult = iiQuery(result.parameter, segInterval);
173  if (iiResult.intersect)
174  {
175  result.numIntersections = iiResult.numIntersections;
176  result.parameter = iiResult.overlap;
177  }
178  else
179  {
180  result.intersect = false;
181  result.numIntersections = 0;
182  }
183  }
184 }
185 
186 
187 }
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:255
Result operator()(Type0 const &primitive0, Type1 const &primitive1)
GLuint64EXT * result
Definition: glext.h:10003


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:00