1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5 
6 //
7 // A 3D plane class template
8 //
9 
10 #ifndef INCLUDED_IMATHPLANE_H
11 #define INCLUDED_IMATHPLANE_H
12 
13 #include "ImathExport.h"
14 #include "ImathNamespace.h"
15 
16 #include "ImathLine.h"
17 #include "ImathVec.h"
18 
19 IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
20 
21 ///
22 /// The `Plane3` class represents a half space in 3D, so the normal
23 /// may point either towards or away from origin.  The plane `P` can
24 /// be represented by Plane3 as either `p` or `-p` corresponding to
25 /// the two half-spaces on either side of the plane. Any function
26 /// which computes a distance will return either negative or positive
27 /// values for the distance indicating which half-space the point is
28 /// in. Note that reflection, and intersection functions will operate
29 /// as expected.
30 
31 template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Plane3
32 {
33   public:
34 
35     /// @{
36     /// @name Direct access to member fields
37 
38     /// The normal to the plane
39     Vec3<T> normal;
40 
41     /// The distance from the origin to the plane
42     T distance;
43 
44     /// @}
45 
46     /// @{
47     ///	@name Constructors
48 
49     /// Uninitialized by default
Plane3()50     IMATH_HOSTDEVICE Plane3() IMATH_NOEXCEPT {}
51 
52     /// Initialize with a normal and distance
53     IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Plane3 (const Vec3<T>& normal, T distance) IMATH_NOEXCEPT;
54 
55     /// Initialize with a point and a normal
56     IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Plane3 (const Vec3<T>& point, const Vec3<T>& normal) IMATH_NOEXCEPT;
57 
58     /// Initialize with three points
59     IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Plane3 (const Vec3<T>& point1,
60                                                const Vec3<T>& point2,
61                                                const Vec3<T>& point3) IMATH_NOEXCEPT;
62 
63     /// @}
64 
65     /// @{
66     /// @name Manipulation
67 
68     /// Set via a given normal and distance
69     IMATH_HOSTDEVICE void set (const Vec3<T>& normal, T distance) IMATH_NOEXCEPT;
70 
71     /// Set via a given point and normal
72     IMATH_HOSTDEVICE void set (const Vec3<T>& point, const Vec3<T>& normal) IMATH_NOEXCEPT;
73 
74     /// Set via three points
75     IMATH_HOSTDEVICE void set (const Vec3<T>& point1, const Vec3<T>& point2, const Vec3<T>& point3) IMATH_NOEXCEPT;
76 
77     /// @}
78 
79     /// @{
80     /// @name Utility Methods
81 
82     /// Determine if a line intersects the plane.
83     /// @param line The line
84     /// @param[out] intersection The point of intersection
85     /// @return True if the line intersects the plane.
86     IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
87     intersect (const Line3<T>& line, Vec3<T>& intersection) const IMATH_NOEXCEPT;
88 
89     /// Determine if a line intersects the plane.
90     /// @param line The line
91     /// @param[out] parameter The parametric value of the point of intersection
92     /// @return True if the line intersects the plane.
93     IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersectT (const Line3<T>& line, T& parameter) const IMATH_NOEXCEPT;
94 
95     /// Return the distance from a point to the plane.
96     IMATH_HOSTDEVICE constexpr T distanceTo (const Vec3<T>& point) const IMATH_NOEXCEPT;
97 
98     /// Reflect the given point around the plane.
99     IMATH_HOSTDEVICE constexpr Vec3<T> reflectPoint (const Vec3<T>& point) const IMATH_NOEXCEPT;
100 
101     /// Reflect the direction vector around the plane
102     IMATH_HOSTDEVICE constexpr Vec3<T> reflectVector (const Vec3<T>& vec) const IMATH_NOEXCEPT;
103 
104     /// @}
105 };
106 
107 /// Plane of type float
108 typedef Plane3<float> Plane3f;
109 
110 /// Plane of type double
111 typedef Plane3<double> Plane3d;
112 
113 //---------------
114 // Implementation
115 //---------------
116 
117 template <class T>
Plane3(const Vec3<T> & p0,const Vec3<T> & p1,const Vec3<T> & p2)118 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Plane3<T>::Plane3 (const Vec3<T>& p0, const Vec3<T>& p1, const Vec3<T>& p2) IMATH_NOEXCEPT
119 {
120     set (p0, p1, p2);
121 }
122 
123 template <class T>
Plane3(const Vec3<T> & n,T d)124 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Plane3<T>::Plane3 (const Vec3<T>& n, T d) IMATH_NOEXCEPT
125 {
126     set (n, d);
127 }
128 
129 template <class T>
Plane3(const Vec3<T> & p,const Vec3<T> & n)130 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Plane3<T>::Plane3 (const Vec3<T>& p, const Vec3<T>& n) IMATH_NOEXCEPT
131 {
132     set (p, n);
133 }
134 
135 template <class T>
136 IMATH_HOSTDEVICE inline void
set(const Vec3<T> & point1,const Vec3<T> & point2,const Vec3<T> & point3)137 Plane3<T>::set (const Vec3<T>& point1, const Vec3<T>& point2, const Vec3<T>& point3) IMATH_NOEXCEPT
138 {
139     normal = (point2 - point1) % (point3 - point1);
140     normal.normalize();
141     distance = normal ^ point1;
142 }
143 
144 template <class T>
145 IMATH_HOSTDEVICE inline void
set(const Vec3<T> & point,const Vec3<T> & n)146 Plane3<T>::set (const Vec3<T>& point, const Vec3<T>& n) IMATH_NOEXCEPT
147 {
148     normal = n;
149     normal.normalize();
150     distance = normal ^ point;
151 }
152 
153 template <class T>
154 IMATH_HOSTDEVICE inline void
set(const Vec3<T> & n,T d)155 Plane3<T>::set (const Vec3<T>& n, T d) IMATH_NOEXCEPT
156 {
157     normal = n;
158     normal.normalize();
159     distance = d;
160 }
161 
162 template <class T>
163 IMATH_HOSTDEVICE constexpr inline T
distanceTo(const Vec3<T> & point)164 Plane3<T>::distanceTo (const Vec3<T>& point) const IMATH_NOEXCEPT
165 {
166     return (point ^ normal) - distance;
167 }
168 
169 template <class T>
170 IMATH_HOSTDEVICE constexpr inline Vec3<T>
reflectPoint(const Vec3<T> & point)171 Plane3<T>::reflectPoint (const Vec3<T>& point) const IMATH_NOEXCEPT
172 {
173     return normal * distanceTo (point) * -2.0 + point;
174 }
175 
176 template <class T>
177 IMATH_HOSTDEVICE constexpr inline Vec3<T>
reflectVector(const Vec3<T> & v)178 Plane3<T>::reflectVector (const Vec3<T>& v) const IMATH_NOEXCEPT
179 {
180     return normal * (normal ^ v) * 2.0 - v;
181 }
182 
183 template <class T>
184 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
intersect(const Line3<T> & line,Vec3<T> & point)185 Plane3<T>::intersect (const Line3<T>& line, Vec3<T>& point) const IMATH_NOEXCEPT
186 {
187     T d = normal ^ line.dir;
188     if (d == 0.0)
189         return false;
190     T t   = -((normal ^ line.pos) - distance) / d;
191     point = line (t);
192     return true;
193 }
194 
195 template <class T>
196 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
intersectT(const Line3<T> & line,T & t)197 Plane3<T>::intersectT (const Line3<T>& line, T& t) const IMATH_NOEXCEPT
198 {
199     T d = normal ^ line.dir;
200     if (d == 0.0)
201         return false;
202     t = -((normal ^ line.pos) - distance) / d;
203     return true;
204 }
205 
206 /// Stream output, as "(normal distance)"
207 template <class T>
208 std::ostream&
209 operator<< (std::ostream& o, const Plane3<T>& plane)
210 {
211     return o << "(" << plane.normal << ", " << plane.distance << ")";
212 }
213 
214 /// Transform a plane by a matrix
215 template <class T>
216 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Plane3<T>
217 operator* (const Plane3<T>& plane, const Matrix44<T>& M) IMATH_NOEXCEPT
218 {
219     //                        T
220     //	                    -1
221     //	Could also compute M    but that would suck.
222     //
223 
224     Vec3<T> dir1 = Vec3<T> (1, 0, 0) % plane.normal;
225     T dir1Len    = dir1 ^ dir1;
226 
227     Vec3<T> tmp = Vec3<T> (0, 1, 0) % plane.normal;
228     T tmpLen    = tmp ^ tmp;
229 
230     if (tmpLen > dir1Len)
231     {
232         dir1    = tmp;
233         dir1Len = tmpLen;
234     }
235 
236     tmp    = Vec3<T> (0, 0, 1) % plane.normal;
237     tmpLen = tmp ^ tmp;
238 
239     if (tmpLen > dir1Len)
240     {
241         dir1 = tmp;
242     }
243 
244     Vec3<T> dir2  = dir1 % plane.normal;
245     Vec3<T> point = plane.distance * plane.normal;
246 
247     return Plane3<T> (point * M, (point + dir2) * M, (point + dir1) * M);
248 }
249 
250 /// Reflect the pla
251 template <class T>
252 IMATH_HOSTDEVICE constexpr inline Plane3<T>
253 operator- (const Plane3<T>& plane) IMATH_NOEXCEPT
254 {
255     return Plane3<T> (-plane.normal, -plane.distance);
256 }
257 
258 IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
259 
260 #endif // INCLUDED_IMATHPLANE_H
261