GteIntrSphere3Cone3.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>
12 #include <Mathematics/GteCone.h>
13 #include <Mathematics/GteFIQuery.h>
14 #include <Mathematics/GteTIQuery.h>
15 
16 namespace gte
17 {
18 
19 template <typename Real>
20 class TIQuery<Real, Sphere3<Real>, Cone3<Real>>
21 {
22 public:
23  struct Result
24  {
25  bool intersect;
26  };
27 
28  Result operator()(Sphere3<Real> const& sphere, Cone3<Real> const& cone);
29 };
30 
31 template <typename Real>
32 class FIQuery<Real, Sphere3<Real>, Cone3<Real>>
33 {
34 public:
35  struct Result
36  {
37  // If an intersection occurs, it is potentially an infinite set. If
38  // the cone vertex is inside the sphere, 'point' is set to the cone
39  // vertex; else if the sphere center is inside the cone, 'point' is
40  // set to the sphere center; else 'point' is set to the cone point
41  // closest to the cone vertex.
42  bool intersect;
44  };
45 
46  Result operator()(Sphere3<Real> const& sphere, Cone3<Real> const& cone);
47 };
48 
49 
50 template <typename Real>
53  Sphere3<Real> const& sphere, Cone3<Real> const& cone)
54 {
55  Result result;
56 
57  Real invSin = ((Real)1) / cone.sinAngle;
58  Real cosSqr = cone.cosAngle * cone.cosAngle;
59  Vector3<Real> CmV = sphere.center - cone.ray.origin;
60  Vector3<Real> D = CmV + (sphere.radius * invSin) * cone.ray.direction;
61  Real lenSqr = Dot(D, D);
62  Real e = Dot(D, cone.ray.direction);
63  if (e > (Real)0 && e*e >= lenSqr*cosSqr)
64  {
65  Real sinSqr = cone.sinAngle * cone.sinAngle;
66  lenSqr = Dot(CmV, CmV);
67  e = -Dot(CmV, cone.ray.direction);
68  if (e > (Real)0 && e*e >= lenSqr*sinSqr)
69  {
70  Real rSqr = sphere.radius * sphere.radius;
71  result.intersect = (lenSqr <= rSqr);
72  }
73  else
74  {
75  result.intersect = true;
76  }
77  }
78  else
79  {
80  result.intersect = false;
81  }
82 
83  return result;
84 }
85 
86 template <typename Real>
89  Sphere3<Real> const& sphere, Cone3<Real> const& cone)
90 {
91  Result result;
92 
93  // Test whether the cone vertex is inside the sphere.
94  Vector3<Real> diff = sphere.center - cone.ray.origin;
95  Real rSqr = sphere.radius * sphere.radius;
96  Real lenSqr = Dot(diff, diff);
97  if (lenSqr <= rSqr)
98  {
99  // The cone vertex is inside the sphere, so the sphere and cone
100  // intersect.
101  result.intersect = true;
102  result.point = cone.ray.origin;
103  return result;
104  }
105 
106  // Test whether the sphere center is inside the cone.
107  Real dot = Dot(diff, cone.ray.direction);
108  Real dotSqr = dot*dot;
109  Real cosSqr = cone.cosAngle * cone.cosAngle;
110  if (dotSqr >= lenSqr*cosSqr && dot > (Real)0)
111  {
112  // The sphere center is inside cone, so the sphere and cone
113  // intersect.
114  result.intersect = true;
115  result.point = sphere.center;
116  return result;
117  }
118 
119  // The sphere center is outside the cone. The problem now reduces to
120  // computing an intersection between the circle and the ray in the plane
121  // containing the cone vertex and spanned by the cone axis and vector
122  // from the cone vertex to the sphere center.
123 
124  // The ray is t*D+V (t >= 0) where |D| = 1 and dot(A,D) = cos(angle).
125  // Also, D = e*A+f*(C-V). Plugging the ray equation into sphere equation
126  // yields R^2 = |t*D+V-C|^2, so the quadratic for intersections is
127  // t^2 - 2*dot(D,C-V)*t + |C-V|^2 - R^2 = 0. An intersection occurs
128  // if and only if the discriminant is nonnegative. This test becomes
129  //
130  // dot(D,C-V)^2 >= dot(C-V,C-V) - R^2
131  //
132  // Note that if the right-hand side is nonpositive, then the inequality
133  // is true (the sphere contains V). This is already ruled out in the
134  // first block of code in this function.
135 
136  Real uLen = sqrt(std::max(lenSqr - dotSqr, (Real)0));
137  Real test = cone.cosAngle * dot + cone.sinAngle * uLen;
138  Real discr = test * test - lenSqr + rSqr;
139 
140  if (discr >= (Real)0 && test >= (Real)0)
141  {
142  // Compute the point of intersection closest to the cone vertex.
143  result.intersect = true;
144  Real t = test - sqrt(std::max(discr, (Real)0));
145  Vector3<Real> B = diff - dot * cone.ray.direction;
146  Real tmp = cone.sinAngle / uLen;
147  result.point = t * (cone.cosAngle * cone.ray.direction + tmp * B);
148  }
149  else
150  {
151  result.intersect = false;
152  }
153 
154  return result;
155 }
156 
157 
158 }
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLdouble GLdouble t
Definition: glext.h:239
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