GteIntrDisk2Sector2.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/GteSector2.h>
12 #include <Mathematics/GteTIQuery.h>
13 
14 // The Circle2 object is considered to be a disk whose points X satisfy the
15 // constraint |X-C| <= R, where C is the disk center and R is the disk
16 // radius. The Sector2 object is also considered to be a solid. Also,
17 // the Sector2 object is required to be convex, so the sector angle must
18 // be in (0,pi/2], even though the Sector2 definition allows for angles
19 // larger than pi/2 (leading to nonconvex sectors). The sector vertex is
20 // V, the radius is L, the axis direction is D, and the angle is A. Sector
21 // points X satisfy |X-V| <= L and Dot(D,X-V) >= cos(A)|X-V| >= 0.
22 //
23 // A subproblem for the test-intersection query is to determine whether
24 // the disk intersects the cone of the sector. Although the query is in
25 // 2D, it is analogous to the 3D problem of determining whether a sphere
26 // and cone overlap. That algorithm is described in
27 // http://www.geometrictools.com/Documentation/IntersectionSphereCone.pdf
28 // The algorithm leads to coordinate-free pseudocod which applies to 2D
29 // as well as 3D. That function is the first SphereIntersectsCone on
30 // page 4 of the PDF.
31 //
32 // If the disk is outside the cone, there is no intersection. If the disk
33 // overlaps the cone, we then need to test whether the disk overlaps the
34 // disk of the sector.
35 
36 namespace gte
37 {
38 
39 template <typename Real>
40 class TIQuery<Real, Circle2<Real>, Sector2<Real>>
41 {
42 public:
43  struct Result
44  {
45  bool intersect;
46  };
47 
48  Result operator()(Circle2<Real> const& disk, Sector2<Real> const& sector);
49 };
50 
51 template <typename Real>
54  Circle2<Real> const& disk, Sector2<Real> const& sector)
55 {
56  Result result;
57 
58  // Test whether the disk and the disk of the sector overlap.
59  Vector2<Real> CmV = disk.center - sector.vertex;
60  Real sqrLengthCmV = Dot(CmV, CmV);
61  Real lengthCmV = sqrt(sqrLengthCmV);
62  if (lengthCmV > disk.radius + sector.radius)
63  {
64  // The disk is outside the disk of the sector.
65  result.intersect = false;
66  return result;
67  }
68 
69  // Test whether the disk and cone of the sector overlap. The comments
70  // about K, K', and K" refer to the PDF mentioned previously.
71  Vector2<Real> U = sector.vertex - (disk.radius / sector.sinAngle) * sector.direction;
72  Vector2<Real> CmU = disk.center - U;
73  Real lengthCmU = Length(CmU);
74  if (Dot(sector.direction, CmU) < lengthCmU * sector.cosAngle)
75  {
76  // The disk center is outside K" (in the white or gray regions).
77  result.intersect = false;
78  return result;
79  }
80  // The disk center is inside K" (in the red, orange, blue, or green regions).
81  Real dotDirCmV = Dot(sector.direction, CmV);
82  if (-dotDirCmV >= lengthCmV * sector.sinAngle)
83  {
84  // The disk center is inside K" and inside K' (in the blue or green regions).
85  if (lengthCmV <= disk.radius)
86  {
87  // The disk center is in the blue region, in which case the disk
88  // contains the sector's vertex.
89  result.intersect = true;
90  }
91  else
92  {
93  // The disk center is in the green region.
94  result.intersect = false;
95  }
96  return result;
97  }
98 
99  // To reach here, we know that the disk overlaps the sector's disk and
100  // the sector's cone. The disk center is in the orange region or in
101  // in the red region (not including the segments that separate the red
102  // and blue regions).
103 
104  // Test whether the ray of the right boundary of the sector overlaps
105  // the disk. The ray direction U0 is a clockwise rotation of the
106  // cone axis by the cone angle.
107  Vector2<Real> U0
108  {
109  +sector.cosAngle * sector.direction[0] + sector.sinAngle * sector.direction[1],
110  -sector.sinAngle * sector.direction[0] + sector.cosAngle * sector.direction[1]
111  };
112  Real dp0 = Dot(U0, CmV);
113  Real discr0 = disk.radius * disk.radius + dp0 * dp0 - sqrLengthCmV;
114  if (discr0 >= (Real)0)
115  {
116  // The ray intersects the disk. Now test whether the sector boundary
117  // segment contained by the ray overlaps the disk. The quadratic
118  // root tmin generates the ray-disk point of intersection closest to
119  // the sector vertex.
120  Real tmin = dp0 - sqrt(discr0);
121  if (sector.radius >= tmin)
122  {
123  // The segment overlaps the disk.
124  result.intersect = true;
125  return result;
126  }
127  else
128  {
129  // The segment does not overlap the disk. We know the disks
130  // overlap, so if the disk center is outside the sector cone
131  // or on the right-boundary ray, the overlap occurs outside the
132  // cone, which implies the disk and sector do not intersect.
133  if (dotDirCmV <= lengthCmV * sector.cosAngle)
134  {
135  // The disk center is not inside the sector cone.
136  result.intersect = false;
137  return result;
138  }
139  }
140  }
141 
142  // Test whether the ray of the left boundary of the sector overlaps
143  // the disk. The ray direction U1 is a counterclockwise rotation of the
144  // cone axis by the cone angle.
145  Vector2<Real> U1
146  {
147  +sector.cosAngle * sector.direction[0] - sector.sinAngle * sector.direction[1],
148  +sector.sinAngle * sector.direction[0] + sector.cosAngle * sector.direction[1]
149  };
150  Real dp1 = Dot(U1, CmV);
151  Real discr1 = disk.radius * disk.radius + dp1 * dp1 - sqrLengthCmV;
152  if (discr1 >= (Real)0)
153  {
154  // The ray intersects the disk. Now test whether the sector boundary
155  // segment contained by the ray overlaps the disk. The quadratic
156  // root tmin generates the ray-disk point of intersection closest to
157  // the sector vertex.
158  Real tmin = dp1 - sqrt(discr1);
159  if (sector.radius >= tmin)
160  {
161  result.intersect = true;
162  return result;
163  }
164  else
165  {
166  // The segment does not overlap the disk. We know the disks
167  // overlap, so if the disk center is outside the sector cone
168  // or on the right-boundary ray, the overlap occurs outside the
169  // cone, which implies the disk and sector do not intersect.
170  if (dotDirCmV <= lengthCmV * sector.cosAngle)
171  {
172  // The disk center is not inside the sector cone.
173  result.intersect = false;
174  return result;
175  }
176  }
177  }
178 
179  // To reach here, a strict subset of the sector's arc boundary must
180  // intersect the disk.
181  result.intersect = true;
182  return result;
183 }
184 
185 }
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
DualQuaternion< Real > Length(DualQuaternion< Real > const &d, bool robust=false)
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