GteIntrPlane3Cylinder3.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 <LowLevel/GteLogger.h>
12 #include <Mathematics/GteCircle3.h>
15 #include <Mathematics/GteLine.h>
16 #include <Mathematics/GteFIQuery.h>
17 #include <Mathematics/GteTIQuery.h>
18 
19 namespace gte
20 {
21 
22 template <typename Real>
23 class TIQuery<Real, Plane3<Real>, Cylinder3<Real>>
24 {
25 public:
26  struct Result
27  {
28  bool intersect;
29  };
30 
31  // The cylinder must have finite height.
32  Result operator()(Plane3<Real> const& plane,
33  Cylinder3<Real> const& cylinder);
34 };
35 
36 template <typename Real>
37 class FIQuery<Real, Plane3<Real>, Cylinder3<Real>>
38 {
39 public:
40  struct Result
41  {
42  bool intersect;
43 
44  // The type of intersection.
45  // 0: none
46  // 1: single line (cylinder is tangent to plane), line[0] valid
47  // 2: two parallel lines (plane cuts cylinder in two lines)
48  // 3: circle (cylinder axis perpendicular to plane)
49  // 4: ellipse (cylinder axis neither parallel nor perpendicular)
50  int type;
51  Line3<Real> line[2];
54  };
55 
56  // The cylinder must have infinite height.
57  Result operator()(Plane3<Real> const& plane,
58  Cylinder3<Real> const& cylinder);
59 };
60 
61 
62 template <typename Real>
65  Plane3<Real> const& plane, Cylinder3<Real> const& cylinder)
66 {
67  LogAssert(cylinder.height != std::numeric_limits<Real>::max(),
68  "Cylinder height must be finite for TIQuery.");
69 
70  Result result;
71 
72  // Compute extremes of signed distance Dot(N,X)-d for points on the
73  // cylinder. These are
74  // min = (Dot(N,C)-d) - r*sqrt(1-Dot(N,W)^2) - (h/2)*|Dot(N,W)|
75  // max = (Dot(N,C)-d) + r*sqrt(1-Dot(N,W)^2) + (h/2)*|Dot(N,W)|
77  Real distance = vpQuery(cylinder.axis.origin, plane).distance;
78  Real absNdW = std::abs(Dot(plane.normal, cylinder.axis.direction));
79  Real root = sqrt(std::max((Real)1 - absNdW*absNdW, (Real)0));
80  Real term = cylinder.radius*root + ((Real)0.5)*cylinder.height*absNdW;
81 
82  // Intersection occurs if and only if 0 is in the interval [min,max].
83  result.intersect = (distance <= term);
84  return result;
85 }
86 
87 template <typename Real>
90  Plane3<Real> const& plane, Cylinder3<Real> const& cylinder)
91 {
92  LogAssert(cylinder.height == std::numeric_limits<Real>::max(),
93  "Cylinder height must be infinite for FIQuery.");
94 
95  Result result;
96 
98  Real sdistance = vpQuery(cylinder.axis.origin, plane).signedDistance;
99  Vector3<Real> center = cylinder.axis.origin - sdistance*plane.normal;
100  Real cosTheta = Dot(cylinder.axis.direction, plane.normal);
101  Real absCosTheta = std::abs(cosTheta);
102 
103  if (absCosTheta > (Real)0)
104  {
105  // The cylinder axis intersects the plane in a unique point.
106  result.intersect = true;
107  if (absCosTheta < (Real)1)
108  {
109  result.type = 4;
110  result.ellipse.normal = plane.normal;
111  result.ellipse.center = cylinder.axis.origin -
112  (sdistance / cosTheta)*cylinder.axis.direction;
113  result.ellipse.axis[0] = cylinder.axis.direction -
114  cosTheta*plane.normal;
115  Normalize(result.ellipse.axis[0]);
116  result.ellipse.axis[1] = UnitCross(plane.normal,
117  result.ellipse.axis[0]);
118  result.ellipse.extent[0] = cylinder.radius / absCosTheta;
119  result.ellipse.extent[1] = cylinder.radius;
120  }
121  else
122  {
123  result.type = 3;
124  result.circle.normal = plane.normal;
125  result.circle.center = center;
126  result.circle.radius = cylinder.radius;
127  }
128  }
129  else
130  {
131  // The cylinder is parallel to the plane.
132  Real distance = std::abs(sdistance);
133  if (distance < cylinder.radius)
134  {
135  result.intersect = true;
136  result.type = 2;
137 
138  Vector3<Real> offset = Cross(cylinder.axis.direction,
139  plane.normal);
140  Real extent = sqrt(cylinder.radius*cylinder.radius -
141  sdistance*sdistance);
142 
143  result.line[0].origin = center - extent*offset;
144  result.line[0].direction = cylinder.axis.direction;
145  result.line[1].origin = center + extent*offset;
146  result.line[1].direction = cylinder.axis.direction;
147  }
148  else if (distance == cylinder.radius)
149  {
150  result.intersect = true;
151  result.type = 1;
152  result.line[0].origin = center;
153  result.line[0].direction = cylinder.axis.direction;
154  }
155  else
156  {
157  result.intersect = false;
158  result.type = 0;
159  }
160  }
161 
162  return result;
163 }
164 
165 
166 }
gte::BSNumber< UIntegerType > abs(gte::BSNumber< UIntegerType > const &number)
Definition: GteBSNumber.h:966
#define LogAssert(condition, message)
Definition: GteLogger.h:86
Vector< N, Real > UnitCross(Vector< N, Real > const &v0, Vector< N, Real > const &v1, bool robust=false)
Definition: GteVector3.h:130
GLsizei GLsizei GLfloat distance
Definition: glext.h:9704
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
Real Normalize(GVector< Real > &v, bool robust=false)
Definition: GteGVector.h:454
DualQuaternion< Real > Cross(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
GLintptr offset
Definition: glcorearb.h:660
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