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