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_PLANE_H 25 #define PXR_BASE_GF_PLANE_H 26 27 /// \file gf/plane.h 28 /// \ingroup group_gf_BasicGeometry 29 30 #include "pxr/pxr.h" 31 #include "pxr/base/gf/vec3d.h" 32 #include "pxr/base/gf/api.h" 33 34 #include <iosfwd> 35 36 PXR_NAMESPACE_OPEN_SCOPE 37 38 class GfRange3d; 39 class GfMatrix4d; 40 class GfVec4d; 41 42 /// \class GfPlane 43 /// \ingroup group_gf_BasicGeometry 44 /// 45 /// Basic type: 3-dimensional plane 46 /// 47 /// This class represents a three-dimensional plane as a normal vector 48 /// and the distance of the plane from the origin, measured along the 49 /// normal. The plane can also be used to represent a half-space: the 50 /// side of the plane in the direction of the normal. 51 /// 52 class GfPlane 53 { 54 public: 55 56 /// The default constructor leaves the plane parameters undefined. GfPlane()57 GfPlane() { 58 } 59 60 /// This constructor sets this to the plane perpendicular to \p normal and 61 /// at \p distance units from the origin. The passed-in normal is 62 /// normalized to unit length first. GfPlane(const GfVec3d & normal,double distanceToOrigin)63 GfPlane(const GfVec3d &normal, double distanceToOrigin) { 64 Set(normal, distanceToOrigin); 65 } 66 67 /// This constructor sets this to the plane perpendicular to \p normal and 68 /// that passes through \p point. The passed-in normal is normalized to 69 /// unit length first. GfPlane(const GfVec3d & normal,const GfVec3d & point)70 GfPlane(const GfVec3d &normal, const GfVec3d &point) { 71 Set(normal, point); 72 } 73 74 /// This constructor sets this to the plane that contains the three given 75 /// points. The normal is constructed from the cross product of (\p p1 - 76 /// \p p0) (\p p2 - \p p0). Results are undefined if the points are 77 /// collinear. GfPlane(const GfVec3d & p0,const GfVec3d & p1,const GfVec3d & p2)78 GfPlane(const GfVec3d &p0, const GfVec3d &p1, const GfVec3d &p2) { 79 Set(p0, p1, p2); 80 } 81 82 /// This constructor creates a plane given by the equation 83 /// \p eqn[0] * x + \p eqn[1] * y + \p eqn[2] * z + \p eqn[3] = 0. GfPlane(const GfVec4d & eqn)84 GfPlane(const GfVec4d &eqn) { 85 Set(eqn); 86 } 87 88 /// Sets this to the plane perpendicular to \p normal and at \p distance 89 /// units from the origin. The passed-in normal is normalized to unit 90 /// length first. Set(const GfVec3d & normal,double distanceToOrigin)91 void Set(const GfVec3d &normal, double distanceToOrigin) { 92 _normal = normal.GetNormalized(); 93 _distance = distanceToOrigin; 94 } 95 96 /// This constructor sets this to the plane perpendicular to \p normal and 97 /// that passes through \p point. The passed-in normal is normalized to 98 /// unit length first. 99 GF_API 100 void Set(const GfVec3d &normal, const GfVec3d &point); 101 102 /// This constructor sets this to the plane that contains the three given 103 /// points. The normal is constructed from the cross product of (\p p1 - 104 /// \p p0) (\p p2 - \p p0). Results are undefined if the points are 105 /// collinear. 106 GF_API 107 void Set(const GfVec3d &p0, 108 const GfVec3d &p1, 109 const GfVec3d &p2); 110 111 /// This method sets this to the plane given by the equation 112 /// \p eqn[0] * x + \p eqn[1] * y + \p eqn[2] * z + \p eqn[3] = 0. 113 GF_API 114 void Set(const GfVec4d &eqn); 115 116 /// Returns the unit-length normal vector of the plane. GetNormal()117 const GfVec3d & GetNormal() const { 118 return _normal; 119 } 120 121 /// Returns the distance of the plane from the origin. GetDistanceFromOrigin()122 double GetDistanceFromOrigin() const { 123 return _distance; 124 } 125 126 /// Give the coefficients of the equation of the plane. Suitable 127 /// to OpenGL calls to set the clipping plane. 128 GF_API 129 GfVec4d GetEquation() const; 130 131 /// Component-wise equality test. The normals and distances must match 132 /// exactly for planes to be considered equal. 133 bool operator ==(const GfPlane &p) const { 134 return (_normal == p._normal && 135 _distance == p._distance); 136 } 137 138 /// Component-wise inequality test. The normals and distances must match 139 /// exactly for planes to be considered equal. 140 bool operator !=(const GfPlane &p) const { 141 return ! (*this == p); 142 } 143 144 /// Returns the distance of point \p from the plane. This distance will be 145 /// positive if the point is on the side of the plane containing the 146 /// normal. GetDistance(const GfVec3d & p)147 double GetDistance(const GfVec3d &p) const { 148 return p * _normal - _distance; 149 } 150 151 /// Return the projection of \p p onto the plane. Project(const GfVec3d & p)152 GfVec3d Project(const GfVec3d& p) const { 153 return p - GetDistance(p) * _normal; 154 } 155 156 /// Transforms the plane by the given matrix. 157 GF_API 158 GfPlane & Transform(const GfMatrix4d &matrix); 159 160 /// Flip the plane normal (if necessary) so that \p p is in the positive 161 /// halfspace. Reorient(const GfVec3d & p)162 void Reorient(const GfVec3d& p) { 163 if (GetDistance(p) < 0) { 164 _normal = -_normal; 165 _distance = -_distance; 166 } 167 } 168 169 /// Returns \c true if the given aligned bounding box is at least 170 /// partially on the positive side (the one the normal points into) of the 171 /// plane. 172 GF_API 173 bool IntersectsPositiveHalfSpace(const GfRange3d &box) const; 174 175 /// Returns true if the given point is on the plane or within its positive 176 /// half space. IntersectsPositiveHalfSpace(const GfVec3d & pt)177 bool IntersectsPositiveHalfSpace(const GfVec3d &pt) const { 178 return GetDistance(pt) >= 0.0; 179 } 180 181 private: 182 /// The normal to the plane. Points in direction of half-space. 183 GfVec3d _normal; 184 185 /// Distance from the plane to the origin. 186 double _distance; 187 }; 188 189 /// Fits a plane to the given \p points. There must be at least three points in 190 /// order to fit the plane; if the size of \p points is less than three, this 191 /// issues a coding error. 192 /// 193 /// If the \p points are all collinear, then no plane can be determined, and 194 /// this function returns \c false. Otherwise, if the fitting is successful, 195 /// it returns \c true and sets \p *fitPlane to the fitted plane. If \p points 196 /// contains exactly three points, then the resulting plane is the exact plane 197 /// defined by the three points. If \p points contains more than three points, 198 /// then this function determines the best-fitting plane for the given points. 199 /// The orientation of the plane normal is arbitrary with regards to the 200 /// plane's positive and negative half-spaces; you can use GfPlane::Reorient() 201 /// to flip the plane if necessary. 202 /// 203 /// The current implementation uses linear least squares and thus defines 204 /// "best-fitting" as minimizing the sum of the squares of the vertical 205 /// distances between points and the plane surface. 206 GF_API 207 bool GfFitPlaneToPoints(const std::vector<GfVec3d>& points, GfPlane* fitPlane); 208 209 /// Output a GfPlane using the format [(nx ny nz) distance]. 210 /// \ingroup group_gf_DebuggingOutput 211 GF_API std::ostream& operator<<(std::ostream&, const GfPlane&); 212 213 PXR_NAMESPACE_CLOSE_SCOPE 214 215 #endif // PXR_BASE_GF_PLANE_H 216