NDEVR
API Documentation
Plane.hpp
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Base
28File: Plane
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/Vertex.h>
34#include <NDEVR/LineSegment.h>
35#include <NDEVR/Matrix.h>
36namespace NDEVR
37{
41 enum class PlanePosition
42 {
43 e_above_plane
44 , e_below_plane
45 , e_on_plane
46 };
47
51 template<uint01 t_dims, class t_type>
52 class Plane
53 {
54 public:
55 Plane()
56 : normal()
57 , d(0)
58 {}
59 constexpr Plane(const Ray<t_dims, t_type>& _normal, const Vertex<t_dims, t_type>& _p)
60 : normal(_normal)
61 , d(dot(_p, _normal))
62 {}
63 constexpr Plane(const Vertex<t_dims, t_type>& a, const Vertex<t_dims, t_type>& b, const Vertex<t_dims, t_type>& c)
64 : normal()
65 , d()
66 {
67 const Vector<t_dims, t_type> edge1 = b - a;
68 const Vector<t_dims, t_type> edge2 = c - a;
69 normal = (cross(edge1, edge2)).template normalized<t_type>(); // Cross product
70 d = dot(a, normal);
71 }
72 constexpr Plane(const Ray<t_dims, t_type>& _normal, t_type _d)
73 : normal(_normal)
74 , d(_d)
75 {}
76 constexpr void negate()
77 {
78 normal = -normal;
79 d = -d;
80 }
81 template<uint01 t_new_dims, class t_new_type>
82 [[nodiscard]] Plane<t_new_dims, t_new_type> as() const
83 {
84 return Plane<t_new_dims, t_new_type>(normal.template as<t_new_dims, t_new_type>(), cast<t_new_type>(d));
85 }
86
87 //untested
88 [[nodiscard]] PlanePosition planePosition(const Vector<t_dims, t_type>& pos) const
89 {
90 t_type dot_product = distanceTo(pos);
91 if (dot_product > 0)
92 return PlanePosition::e_above_plane;
93 else if (dot_product < 0)
94 return PlanePosition::e_below_plane;
95 else
96 return PlanePosition::e_on_plane;
97 }
98 [[nodiscard]] bool isAbovePlane(const Vector<t_dims, t_type>& pos) const
99 {
100 return distanceTo(pos) > 0;
101 }
102 [[nodiscard]] bool isBelowPlane(const Vector<t_dims, t_type>& pos) const
103 {
104 return distanceTo(pos) < 0;
105 }
106 [[nodiscard]] bool liesOnPlane(const Vector<t_dims, t_type>& pos) const
107 {
108 return distanceTo(pos) == 0;
109 }
110 [[nodiscard]] t_type distanceTo(const Vector<t_dims, t_type>& pos) const
111 {
112 return dot(normal, pos) - d;
113 }
114 //end untested
115 [[nodiscard]] Vertex<t_dims, t_type> nearestPosition(const Vector<3, fltp08>& pos) const
116 {
117 t_type V0 = dot(normal, pos) - d;
118 Vector<t_dims, t_type> v = pos - V0 * normal;
119 return v;
120 }
121 [[nodiscard]] t_type calculateIntersectionPos(const LineSegment<t_dims, t_type>& line, t_type epsilon) const
122 {
123 t_type Vd = dot(normal, line.ray());
124 t_type V0 = dot(normal, line[A]) - d;
125
126 if (abs(Vd) < epsilon)
127 {
128 return abs(V0) < epsilon ? Constant<t_type>::Invalid : Constant<t_type>::Max;
129 }
130 t_type distance_along_line = -V0 / Vd;
131 return distance_along_line;
132 }
133
134 [[nodiscard]] Vertex<t_dims, t_type> calculateIntersection(const LineSegment<t_dims, t_type>& line, t_type epsilon) const
135 {
136 t_type distance_along_line = calculateIntersectionPos(line, epsilon);
137 Vertex<t_dims, t_type> v = line[A] + distance_along_line * line.ray();
138 return v;
139 }
140
141 [[nodiscard]] Matrix<t_type> projectionMatrix(const Ray<3, t_type>& up = Ray<3, t_type>(0,0,1)) const
142 {
143 Vector<t_dims, t_type> right = cross(normal, up);
144 if (right == 0.0)
145 {
146 Matrix<t_type> mat(1);
147 if (dot(up, normal) > cast<t_type>(0))
148 {
149 mat[1][1] = cast<t_type>(-1);
150 mat[2][2] = cast<t_type>(-1);
151 }
152 return mat;
153 }
154 right = right.template normalized<t_type>();
155 Vector<t_dims, t_type> backward = cross(normal, right).template normalized<t_type>();
156 Vector<t_dims, t_type> offset = normal * -d;
157 return Matrix<t_type>(
158 right[X], backward[X], normal[X], 0
159 , right[Y], backward[Y], normal[Y], 0
160 , right[Z], backward[Z], normal[Z], 0
161 , offset[X], offset[Y], offset[Z], 1);
162 }
163
164 template<class t_buffer_type>
165 static Plane CreateBestFitPlane(const t_buffer_type& points, const Vector<t_dims, t_type>& direction_reference = Vector<t_dims, t_type>(0,0,1))
166 {
167 const uint04 vertex_size = points.size();
168 lib_assert(vertex_size >= 3, "Plane requires at least 3 points");
169 Vector<t_dims, t_type> centroid(0);
172 Vector<t_dims, t_type> p1, p2, p3, c1, c2;
173
174 p1 = c1 = points[0];
175 p2 = c2 = points[1];
176
177 for(uint04 i = 0; i < vertex_size; i++)
178 {
179 p3 = points[i];
180 v = cross((p3 - p2), (p1 - p2));
181 if(v[t_dims - 1] != 0)
182 v = -v;
183 n += v;
184 p1 = p2;
185 p2 = p3;
186 centroid += points[i];
187 }
188 centroid /= cast<t_type>(vertex_size);
189 p1 = p2;
190 p2 = p3;
191 p3 = c1;
192 v = cross((p3 - p2), (p1 - p2));
193 if(v[t_dims - 1] != 0)
194 v = -v;
195 n += v;
196 p1 = p2;
197 p2 = p3;
198 p3 = c2;
199 v = cross((p3 - p2), (p1 - p2));
200 if (v[t_dims - 1])
201 v = -v;
202 n += v;
203 n = n.template normalized<t_type>();
204 if (dot(direction_reference, n) < 0)
205 n = -n;
206 Plane plane(n, dot(n, centroid));
207 return plane;
208 };
209
210 bool contains(const Vector<3, t_type>& point, t_type epsilon) const
211 {
212 Vector<3, t_type> b = point - (normal * d);
213 return (abs(dot(b, normal)) < epsilon);
214 }
215 bool isSamePlane(const Plane& plane, t_type epsilon) const
216 {
217 return (equals(normal, plane.normal, epsilon) && abs(d - plane.d) < epsilon)
218 || (equals(-normal, plane.normal, epsilon) && abs(d + plane.d) < epsilon);
219 }
220
221 bool operator==(const Plane& plane) const
222 {
223 return normal == plane.normal && d == plane.d;
224 }
225 bool operator!=(const Plane& plane) const
226 {
227 return normal != plane.normal || d != plane.d;
228 }
229 public:
230 Ray<t_dims, t_type> normal;
231 t_type d;
232
233 };
234
244 template<uint01 t_dims, class t_type>
245 struct Constant<Plane<t_dims, t_type>>
246 {
247 constexpr const static Plane<t_dims, t_type> Invalid{ Constant<Vector<t_dims, t_type>>::Invalid, Constant<t_type>::Invalid };
248 };
249
265
266 template<uint01 t_dims, class t_type>
267 static constexpr bool IsInvalid(const Plane<t_dims, t_type>& value)
268 {
269 return IsInvalid(value.normal) || IsInvalid(value.d);
270 }
271 template<uint01 t_dims, class t_type>
272 static constexpr bool IsValid(const Plane<t_dims, t_type>& value)
273 {
274 return !IsInvalid(value.normal) && !IsInvalid(value.d);
275 }
276 template<class t_type, uint01 t_row_dims, uint01 t_col_dims>
278 {
279 Vertex<3, t_type> origin = plane.normal * plane.d;
280 return Plane<3, t_type>((matrix * plane.normal).template normalized<fltp08>(), matrix * origin);
281 }
282};
Class: LineSegment.
Definition Line.hpp:52
constexpr t_vertex ray() const
Definition Line.hpp:123
Templated logic for doing matrix multiplication.
Definition Matrix.hpp:182
Logic for a given plane or N-dimensions.
Definition Plane.hpp:53
A fixed-size array with N dimensions used as the basis for geometric and mathematical types.
Definition Vector.hpp:62
A point in N-dimensional space, used primarily for spatial location information.
Definition Vertex.hpp:44
The primary namespace for the NDEVR SDK.
static constexpr bool IsValid(const Angle< t_type > &value)
Checks whether the given Angle holds a valid value.
Definition Angle.h:398
PlanePosition
The location of an object either below, above, or on a given N-dimensional plane.
Definition Plane.hpp:42
t_type dot(const Vector< t_dims, t_type > &v1, const Vector< t_dims, t_type > &v2)
constexpr Angle< t_angle_type > abs(const Angle< t_angle_type > &value)
Changes an input with a negative sign, to a positive sign.
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
static constexpr Angle< t_type > operator*(const Angle< t_type > &angle_a, const Angle< t_type > &angle_b)
Multiplication operator.
constexpr Vector< 1, t_type > cross(const Vector< 1, t_type > &, const Vector< 1, t_type > &)
static constexpr bool IsInvalid(const Angle< t_type > &value)
Checks whether the given Angle holds an invalid value.
Definition Angle.h:388
constexpr bool equals(const LineSegment< t_dims, t_type, t_vertex > &left, const LineSegment< t_dims, t_type, t_vertex > &right, const t_type &epsilon=cast< t_type >(0))
Tests if objects are considered equal.
Definition Line.hpp:791
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408
Defines for a given type (such as sint04, fltp08, UUID, etc) a maximum, minimum, and reserved 'invali...