1 // 2 // Copyright 2016 Pixar 3 // 4 // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 // with the following modification; you may not use this file except in 6 // compliance with the Apache License and the following modification to it: 7 // Section 6. Trademarks. is deleted and replaced with: 8 // 9 // 6. Trademarks. This License does not grant permission to use the trade 10 // names, trademarks, service marks, or product names of the Licensor 11 // and its affiliates, except as required to comply with Section 4(c) of 12 // the License and to reproduce the content of the NOTICE file. 13 // 14 // You may obtain a copy of the Apache License at 15 // 16 // http://www.apache.org/licenses/LICENSE-2.0 17 // 18 // Unless required by applicable law or agreed to in writing, software 19 // distributed under the Apache License with the above modification is 20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 // KIND, either express or implied. See the Apache License for the specific 22 // language governing permissions and limitations under the Apache License. 23 // 24 #ifndef PXR_BASE_GF_RAY_H 25 #define PXR_BASE_GF_RAY_H 26 27 /// \file gf/ray.h 28 /// \ingroup group_gf_BasicGeometry 29 30 #include "pxr/pxr.h" 31 #include "pxr/base/gf/matrix4d.h" 32 #include "pxr/base/gf/api.h" 33 34 #include <float.h> 35 #include <limits> 36 #include <iosfwd> 37 38 PXR_NAMESPACE_OPEN_SCOPE 39 40 class GfBBox3d; 41 class GfLine; 42 class GfLineSeg; 43 class GfPlane; 44 class GfRange3d; 45 46 /// \class GfRay 47 /// \ingroup group_gf_BasicGeometry 48 /// 49 /// Basic type: Ray used for intersection testing 50 /// 51 /// This class represents a three-dimensional ray in space, typically 52 /// used for intersection testing. It consists of an origin and a 53 /// direction. 54 /// 55 /// Note that by default a \c GfRay does not normalize its direction 56 /// vector to unit length. 57 /// 58 /// Note for ray intersections, the start point is included in the computations, 59 /// i.e., a distance of zero is defined to be intersecting. 60 /// 61 class GfRay { 62 63 public: 64 65 /// The default constructor leaves the ray parameters undefined. GfRay()66 GfRay() { 67 } 68 69 /// This constructor takes a starting point and a direction. GfRay(const GfVec3d & startPoint,const GfVec3d & direction)70 GfRay(const GfVec3d &startPoint, const GfVec3d &direction) { 71 SetPointAndDirection(startPoint, direction); 72 } 73 74 /// Sets the ray by specifying a starting point and a direction. 75 GF_API 76 void SetPointAndDirection(const GfVec3d &startPoint, 77 const GfVec3d &direction); 78 79 /// Sets the ray by specifying a starting point and an ending point. 80 GF_API 81 void SetEnds(const GfVec3d &startPoint, const GfVec3d &endPoint); 82 83 /// Returns the starting point of the segment. GetStartPoint()84 const GfVec3d & GetStartPoint() const { 85 return _startPoint; 86 } 87 88 /// Returns the direction vector of the segment. This is not guaranteed to 89 /// be unit length. GetDirection()90 const GfVec3d & GetDirection() const { 91 return _direction; 92 } 93 94 /// Returns the point that is \p distance units from the starting point 95 /// along the direction vector, expressed in parametic distance. GetPoint(double distance)96 GfVec3d GetPoint(double distance) const { 97 return _startPoint + distance * _direction; 98 } 99 100 /// Transforms the ray by the given matrix. 101 GF_API 102 GfRay & Transform(const GfMatrix4d &matrix); 103 104 /// Returns the point on the ray that is closest to \p point. If \p 105 /// rayDistance is not \c NULL, it will be set to the parametric distance 106 /// along the ray of the closest point. 107 GF_API 108 GfVec3d FindClosestPoint(const GfVec3d &point, 109 double *rayDistance = NULL) const; 110 111 /// Component-wise equality test. The starting points, directions, and 112 /// lengths must match exactly for rays to be considered equal. 113 bool operator ==(const GfRay &r) const { 114 return (_startPoint == r._startPoint && 115 _direction == r._direction); 116 } 117 118 /// Component-wise inequality test. The starting points, directions, and 119 /// lengths must match exactly for rays to be considered equal. 120 bool operator !=(const GfRay &r) const { 121 return ! (*this == r); 122 } 123 124 /// \name Intersection methods. 125 /// 126 /// The methods in this group intersect the ray with a geometric entity. 127 /// 128 ///@{ 129 130 /// Intersects the ray with the triangle formed by points \p p0, \p p1, 131 /// and \p p2, returning \c true if it hits. If there is an intersection, 132 /// it also returns the parametric distance to the intersection point in 133 /// \p distance, the barycentric coordinates of the intersection point in 134 /// \p barycentricCoords and the front-facing flag in \p frontFacing. The 135 /// barycentric coordinates are defined with respect to the three vertices 136 /// taken in order. The front-facing flag is \c true if the intersection 137 /// hit the side of the triangle that is formed when the vertices are 138 /// ordered counter-clockwise (right-hand rule). If any of the return 139 /// pointers are \c NULL, the corresponding values are not returned. 140 /// 141 /// If the distance to the intersection is greater than \p maxDist, then 142 /// the method will return false. 143 /// 144 /// Barycentric coordinates are defined to sum to 1 and satisfy this 145 /// relationsip: 146 /// \code 147 /// intersectionPoint = (barycentricCoords[0] * p0 + 148 /// barycentricCoords[1] * p1 + 149 /// barycentricCoords[2] * p2); 150 /// \endcode 151 GF_API 152 bool Intersect(const GfVec3d &p0, 153 const GfVec3d &p1, 154 const GfVec3d &p2, 155 double *distance = NULL, 156 GfVec3d *barycentricCoords = NULL, 157 bool *frontFacing = NULL, 158 double maxDist = std::numeric_limits<double>::infinity()) 159 const; 160 161 /// Intersects the ray with a plane, returning \c true if the ray is not 162 /// parallel to the plane and the intersection is within the ray bounds. 163 /// If there is an intersection, it also returns the parametric distance 164 /// to the intersection point in \p distance and the front-facing flag in 165 /// \p frontFacing, if they are not \c NULL. The front-facing flag is \c 166 /// true if the intersection is on the side of the plane in which its 167 /// normal points. 168 GF_API 169 bool Intersect(const GfPlane &plane, double *distance = NULL, 170 bool *frontFacing = NULL) const; 171 172 /// Intersects the ray with an axis-aligned box, returning \c true if the 173 /// ray intersects it at all within bounds. If there is an intersection, 174 /// this also returns the parametric distances to the two intersection 175 /// points in \p enterDistance and \p exitDistance. 176 GF_API 177 bool Intersect(const GfRange3d &box, 178 double *enterDistance = NULL, 179 double *exitDistance = NULL) const; 180 181 /// Intersects the ray with an oriented box, returning \c true if the 182 /// ray intersects it at all within bounds. If there is an intersection, 183 /// this also returns the parametric distances to the two intersection 184 /// points in \p enterDistance and \p exitDistance. 185 GF_API 186 bool Intersect(const GfBBox3d &box, 187 double *enterDistance = NULL, 188 double *exitDistance = NULL) const; 189 190 /// Intersects the ray with a sphere, returning \c true if the ray 191 /// intersects it at all within bounds. If there is an intersection, 192 /// returns the parametric distance to the two intersection points in \p 193 /// enterDistance and \p exitDistance. 194 GF_API 195 bool Intersect(const GfVec3d ¢er, double radius, 196 double *enterDistance = NULL, 197 double *exitDistance = NULL ) const; 198 199 /// Intersects the ray with an infinite cylinder, with axis \p axis, 200 /// centered at the \p origin, with radius \p radius. 201 /// 202 /// Returns \c true if the ray intersects it at all within bounds. If 203 /// there is an intersection, returns the parametric distance to the two 204 /// intersection points in \p enterDistance and \p exitDistance. 205 /// 206 /// Note this method does not validate whether the radius is valid. 207 GF_API 208 bool Intersect(const GfVec3d &origin, 209 const GfVec3d &axis, 210 const double radius, 211 double *enterDistance = NULL, 212 double *exitDistance = NULL) const; 213 214 /// Intersects the ray with an infinite non-double cone, centered at \p 215 /// origin, with axis \p axis, radius \p radius and apex at \p height. 216 /// 217 /// Returns \c true if the ray intersects it at all within bounds. If 218 /// there is an intersection, returns the parametric distance to the two 219 /// intersection points in \p enterDistance and \p exitDistance. 220 /// 221 /// Note this method does not validate whether the radius are height are 222 /// valid. 223 GF_API 224 bool Intersect(const GfVec3d &origin, 225 const GfVec3d &axis, 226 const double radius, 227 const double height, 228 double *enterDistance = NULL, 229 double *exitDistance = NULL) const; 230 ///@} 231 232 private: 233 GF_API 234 friend bool GfFindClosestPoints( const GfRay &, const GfLine &, 235 GfVec3d *, GfVec3d *, 236 double *, double * ); 237 GF_API 238 friend bool GfFindClosestPoints( const GfRay &, const GfLineSeg &, 239 GfVec3d *, GfVec3d *, 240 double *, double * ); 241 242 /// Solves the quadratic equation returning the solutions, if defined, in 243 /// \p enterDistance and \p exitDistance, where \p enterDistance is less 244 /// than or equal to \p exitDistance. 245 bool _SolveQuadratic(const double a, 246 const double b, 247 const double c, 248 double *enterDistance = NULL, 249 double *exitDistance = NULL) const; 250 251 /// The starting point of the ray. 252 GfVec3d _startPoint; 253 /// The direction vector. 254 GfVec3d _direction; 255 }; 256 257 /// Computes the closest points between a ray and a line. The two points are 258 /// returned in \p rayPoint and \p linePoint. The parametric distance of each 259 /// point on the lines is returned in \p rayDistance and \p lineDistance. 260 /// 261 /// This returns \c false if the lines were close enough to parallel that no 262 /// points could be computed; in this case, the other return values are 263 /// undefined. 264 GF_API 265 bool GfFindClosestPoints( const GfRay &ray, const GfLine &line, 266 GfVec3d *rayPoint = nullptr, 267 GfVec3d *linePoint = nullptr, 268 double *rayDistance = nullptr, 269 double *lineDistance = nullptr ); 270 271 /// Computes the closest points between a ray and a line segment. The two 272 /// points are returned in \p rayPoint and \p segPoint. The parametric 273 /// distance of each point is returned in \p rayDistance and \p segDistance. 274 /// 275 /// This returns \c false if the lines were close enough to parallel that no 276 /// points could be computed; in this case, the other return values are 277 /// undefined. 278 GF_API 279 bool GfFindClosestPoints( const GfRay &ray, const GfLineSeg &seg, 280 GfVec3d *rayPoint = nullptr, 281 GfVec3d *segPoint = nullptr, 282 double *rayDistance = nullptr, 283 double *segDistance = nullptr ); 284 285 /// Output a GfRay using the format [(x y z) >> (x y z)]. 286 /// \ingroup group_gf_DebuggingOutput 287 GF_API std::ostream& operator<<(std::ostream&, const GfRay&); 288 289 PXR_NAMESPACE_CLOSE_SCOPE 290 291 #endif // PXR_BASE_GF_RAY_H 292