GteIntrCircle2Circle2.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/GteVector2.h>
12 #include <Mathematics/GteFIQuery.h>
13 #include <Mathematics/GteTIQuery.h>
14 #include <limits>
15 
16 namespace gte
17 {
18 
19 template <typename Real>
20 class TIQuery<Real, Circle2<Real>, Circle2<Real>>
21 {
22 public:
23  struct Result
24  {
25  bool intersect;
26  };
27 
28  Result operator()(Circle2<Real> const& circle0,
29  Circle2<Real> const& circle1);
30 };
31 
32 template <typename Real>
33 class FIQuery<Real, Circle2<Real>, Circle2<Real>>
34 {
35 public:
36  struct Result
37  {
38  bool intersect;
39 
40  // The number of intersections is 0, 1, 2, or maxInt =
41  // std::numeric_limits<int>::max(). When 1, the circles are tangent
42  // and intersect in a single point. When 2, circles have two
43  // transverse intersection points. When maxInt, the circles are the
44  // same.
46 
47  // Valid only when numIntersections = 1 or 2.
48  Vector2<Real> point[2];
49 
50  // Valid only when numIntersections = maxInt.
52  };
53 
54  Result operator()(Circle2<Real> const& circle0,
55  Circle2<Real> const& circle1);
56 };
57 
58 
59 template <typename Real>
62  Circle2<Real> const& circle0, Circle2<Real> const& circle1)
63 {
64  Result result;
65  Vector2<Real> diff = circle0.center - circle1.center;
66  result.intersect = (Length(diff) <= circle0.radius + circle1.radius);
67  return result;
68 }
69 
70 template <typename Real>
73  Circle2<Real> const& circle0, Circle2<Real> const& circle1)
74 {
75  // The two circles are |X-C0| = R0 and |X-C1| = R1. Define U = C1 - C0
76  // and V = Perp(U) where Perp(x,y) = (y,-x). Note that Dot(U,V) = 0 and
77  // |V|^2 = |U|^2. The intersection points X can be written in the form
78  // X = C0+s*U+t*V and X = C1+(s-1)*U+t*V. Squaring the circle equations
79  // and substituting these formulas into them yields
80  // R0^2 = (s^2 + t^2)*|U|^2
81  // R1^2 = ((s-1)^2 + t^2)*|U|^2.
82  // Subtracting and solving for s yields
83  // s = ((R0^2-R1^2)/|U|^2 + 1)/2
84  // Then replace in the first equation and solve for t^2
85  // t^2 = (R0^2/|U|^2) - s^2.
86  // In order for there to be solutions, the right-hand side must be
87  // nonnegative. Some algebra leads to the condition for existence of
88  // solutions,
89  // (|U|^2 - (R0+R1)^2)*(|U|^2 - (R0-R1)^2) <= 0.
90  // This reduces to
91  // |R0-R1| <= |U| <= |R0+R1|.
92  // If |U| = |R0-R1|, then the circles are side-by-side and just tangent.
93  // If |U| = |R0+R1|, then the circles are nested and just tangent.
94  // If |R0-R1| < |U| < |R0+R1|, then the two circles to intersect in two
95  // points.
96 
97  Result result;
98 
99  Vector2<Real> U = circle1.center - circle0.center;
100  Real USqrLen = Dot(U, U);
101  Real R0 = circle0.radius, R1 = circle1.radius;
102  Real R0mR1 = R0 - R1;
103  if (USqrLen == (Real)0 && R0mR1 == (Real)0)
104  {
105  // Circles are the same.
106  result.intersect = true;
107  result.numIntersections = std::numeric_limits<int>::max();
108  result.circle = circle0;
109  return result;
110  }
111 
112  Real R0mR1Sqr = R0mR1*R0mR1;
113  if (USqrLen < R0mR1Sqr)
114  {
115  // The circles do not intersect.
116  result.intersect = false;
117  result.numIntersections = 0;
118  return result;
119  }
120 
121  Real R0pR1 = R0 + R1;
122  Real R0pR1Sqr = R0pR1*R0pR1;
123  if (USqrLen > R0pR1Sqr)
124  {
125  // The circles do not intersect.
126  result.intersect = false;
127  result.numIntersections = 0;
128  return result;
129  }
130 
131  if (USqrLen < R0pR1Sqr)
132  {
133  if (R0mR1Sqr < USqrLen)
134  {
135  Real invUSqrLen = ((Real)1) / USqrLen;
136  Real s = ((Real)0.5)*((R0*R0 - R1*R1)*invUSqrLen + (Real)1);
137  Vector2<Real> tmp = circle0.center + s*U;
138 
139  // In theory, discr is nonnegative. However, numerical round-off
140  // errors can make it slightly negative. Clamp it to zero.
141  Real discr = R0*R0*invUSqrLen - s*s;
142  if (discr < (Real)0)
143  {
144  discr = (Real)0;
145  }
146  Real t = sqrt(discr);
147  Vector2<Real> V{ U[1], -U[0] };
148  result.point[0] = tmp - t*V;
149  result.point[1] = tmp + t*V;
150  result.numIntersections = (t >(Real)0 ? 2 : 1);
151  }
152  else
153  {
154  // |U| = |R0-R1|, circles are tangent.
155  result.numIntersections = 1;
156  result.point[0] = circle0.center + (R0 / R0mR1)*U;
157  }
158  }
159  else
160  {
161  // |U| = |R0+R1|, circles are tangent.
162  result.numIntersections = 1;
163  result.point[0] = circle0.center + (R0 / R0pR1)*U;
164  }
165 
166  // The circles intersect in 1 or 2 points.
167  result.intersect = true;
168  return result;
169 }
170 
171 
172 }
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLdouble GLdouble t
Definition: glext.h:239
DualQuaternion< Real > Length(DualQuaternion< Real > const &d, bool robust=false)
GLdouble s
Definition: glext.h:231
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