NDEVR
API Documentation
Line.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: Line
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/BaseValues.h>
34#include <NDEVR/Vertex.h>
35#include <NDEVR/VectorFunctions.h>
36namespace NDEVR
37{
38
50 template<uint01 t_dims, class t_type, class t_vertex = Vertex<t_dims, t_type>>
51 class LineSegment : public Vector<2, t_vertex>
52 {
53 public:
54 constexpr LineSegment()
55 {}
56 constexpr LineSegment(const t_vertex& p1, const t_vertex& p2)
57 : Vector<2, t_vertex>(p1, p2)
58 {}
59 explicit constexpr LineSegment(const Vector<2, t_vertex>& line)
60 : Vector<2, t_vertex>(line)
61 {}
62
72 template<uint01 t_new_dims, class t_new_type, class t_new_vertex = Vertex<t_new_dims, t_new_type>>
73 constexpr LineSegment<t_new_dims, t_new_type, t_new_vertex> as() const
74 {
75 return LineSegment<t_new_dims, t_new_type, t_new_vertex>(t_new_vertex(vertex(A).template as<t_new_dims, t_new_type>()), t_new_vertex(vertex(B).template as<t_new_dims, t_new_type>()));
76 }
77
90 template<class t_inter_type>
91 constexpr inline t_vertex pointAt(t_inter_type index) const
92 {
93 return vertex(A) + (ray().template as<t_dims, t_inter_type>() * index).template as<t_dims, t_type>();
94 }
95
105
106 constexpr inline t_vertex midpoint() const
107 {
108 t_vertex avg = (vertex(A) + vertex(B)) / cast<t_type>(2);
109 avg = clip(avg, getMin(vertex(A), vertex(B)), getMax(vertex(A), vertex(B)));
110 return avg;
111 }
112
122
123 constexpr inline t_vertex ray() const
124 {
125 return vertex(B) - vertex(A);
126 }
127
137
138 constexpr inline t_vertex center() const
139 {
140 return midpoint();
141 }
142
155 constexpr inline const t_vertex& vertex(uint01 index) const
156 {
158 }
159
172 constexpr inline t_vertex& vertex(uint01 index)
173 {
175 }
176
191 template<class t_precision = t_type>
192 constexpr bool isParallel(const LineSegment<t_dims, t_type, t_vertex>& line, t_precision epsilon = 0) const
193 {
194 const Vector<t_dims, t_precision> ray_1( ray().template as<t_dims, t_type>().template normalized<t_precision>());
195 const Vector<t_dims, t_precision> ray_2(line.ray().template as<t_dims, t_type>().template normalized<t_precision>());
196 return (equals(ray_1, ray_2, epsilon) || equals(ray_1, -ray_2, epsilon));
197 }
198
213 template<class t_precision = t_type>
214 constexpr bool isCollinear(const LineSegment<t_dims, t_type>& line, t_precision epsilon = 0) const
215 {
216 return isParallel<t_precision>(line, epsilon) && distanceSquared<t_precision>(line, epsilon) <= epsilon * epsilon;
217 }
218
233 template<class t_precision = t_type>
234 constexpr bool isCollinear(const t_vertex& vert, t_precision epsilon = t_precision(1e-10)) const
235 {
236 const Vector<t_dims, t_precision> ray_1(vertex(B) - vertex(A));
237 const Vector<t_dims, t_precision> ray_2(vert - vertex(A));
238 const Vector<t_dims, t_precision> c = cross(ray_1, ray_2);
239 return c.magnitudeSquared() <= epsilon * ray_1.magnitudeSquared();
240 }
241
242
257 template<class t_precision, class t_other_vertex>
258 constexpr LineSegment<t_dims, t_precision> closestPoints(const LineSegment<t_dims, t_type, t_other_vertex>& l2, t_precision epsilon = 0) const
259 {
260 const Vector<t_dims, t_precision> u( ray());
261 const Vector<t_dims, t_precision> v(l2.ray());
262 const Vector<t_dims, t_precision> w(vertex(A) - l2.vertex(A));
263
264 const t_precision a(dot(u, u));
265 const t_precision b(dot(u, v));
266 const t_precision c(dot(v, v));
267
268 const t_precision d(dot(u, w));
269 const t_precision e(dot(v, w));
270
271 const t_precision D((a * c) - (b * b));
272 t_precision sD = D;
273 t_precision tD = D;
274
275 t_precision sN;
276 t_precision tN;
277 // compute the line parameters of the two closest points
278 if (D > epsilon) // the lines are almost parallel
279 {
280 sN = (b*e - c*d);
281 tN = (a*e - b*d);
282 if (sN < static_cast<t_precision>(0)) // sc < 0 => the s=0 edge is visible
283 {
284 sN = static_cast<t_precision>(0);
285 tN = e;
286 tD = c;
287 }
288 else if (sN > sD) // sc > 1 => the s=1 edge is visible
289 {
290 sN = sD;
291 tN = e + b;
292 tD = c;
293 }
294 }
295 else//Consider the lines parallel
296 {
297 sN = static_cast<t_precision>(0); // force using point P0 on segment S1
298 sD = static_cast<t_precision>(1); // to prevent possible division by 0.0 later
299 tN = e;
300 tD = c;
301 }
302
303 if (tN < static_cast<t_precision>(0)) // tc < 0 => the t=0 edge is visible
304 {
305 tN = static_cast<t_precision>(0);
306 //recompute sc for this edge
307 if (-d < 0)
308 sN = static_cast<t_precision>(0);
309 else if (-d > a)
310 sN = sD;
311 else
312 {
313 sN = -d;
314 sD = a;
315 }
316 }
317 else if (tN > tD) //tc > 1 => the t=1 edge is visible
318 {
319 tN = tD;
320 // recompute sc for this edge
321 if ((-d + b) < static_cast<t_precision>(0))
322 sN = static_cast<t_precision>(0);
323 else if ((-d + b) > a)
324 sN = sD;
325 else
326 {
327 sN = (-d + b);
328 sD = a;
329 }
330 }
331
332 //finally do the division to get sc and tc
333 t_precision sc = abs(sN) <= epsilon ? static_cast<t_precision>(0) : sN / sD;
334 t_precision tc = abs(sN) <= epsilon ? static_cast<t_precision>(0) : tN / tD;
335
336 //get the difference of the two closest points
337 //Vector<t_dims, t_type>dP = w + (u * sc) - (v * tc);
338 //get the difference of the two closest points
339 return LineSegment<t_dims, t_precision>(
340 (u * sc) + vertex(A).template as<t_dims, t_precision>()
341 , (v * tc) + l2.vertex(A).template as<t_dims, t_precision>());
342 }
343
347 template<bool t_clip = true>
348 constexpr t_type closestPos(const t_vertex& p) const
349 {
350 const Vector<t_dims, t_type> ray_1 = ray();
351 const Vector<t_dims, t_type> ray_2 = p - vertex(A);
352
353 t_type sum = (ray_1 * ray_2).sum();
354
355 const t_type mag_squared = ray_1.magnitudeSquared();
356 if (mag_squared != 0)
357 sum /= mag_squared;
358 if constexpr (t_clip)
359 return clip(sum, cast<t_type>(0), cast<t_type>(1));
360 else
361 return sum;
362 }
363
376
377 constexpr t_vertex closestValue(const t_vertex& p) const
378 {
379 return pointAt(closestPos(p));
380 }
381 template<class t_precision = t_type>
382 t_precision distanceSquared(const LineSegment<t_dims, t_type, t_vertex>& right, const t_precision& epsilon = cast<t_precision>(0)) const
383 {
384 return closestPoints<t_precision>(right, epsilon).lengthSquared();
385 }
386
401
416 template<class t_inter_type>
417 constexpr LineSegment<t_dims, t_type> scale(const t_inter_type& scale) const
418 {
419 return LineSegment<t_dims, t_type>(pointAt(-scale / cast<t_inter_type>(2)), pointAt(scale / cast<t_inter_type>(2) + cast<t_inter_type>(1)));
420 }
421 template<class t_inter_type>
422 constexpr LineSegment<t_dims, t_type> scale(const t_inter_type& a_scale, const t_inter_type& b_scale) const
423 {
424 return LineSegment<t_dims, t_type>(pointAt(-a_scale), pointAt(b_scale + cast<t_inter_type>(1)));
425 }
426
427 constexpr LineSegment<t_dims, t_type> extend(const t_type& extension) const
428 {
429 t_vertex dx = (extension / cast<t_type>(2)) * ray().template normalized<t_type>();
430 return LineSegment<t_dims, t_type>(vertex(A) - dx, vertex(B) + dx);
431 }
432 constexpr LineSegment<t_dims, t_type> extend(const t_type& a_extension, const t_type& b_extension) const
433 {
434 t_vertex dx = ray().template normalized<t_type>();
435 return LineSegment<t_dims, t_type>(vertex(A) - (dx * a_extension), vertex(B) + (dx * b_extension));
436 }
446 template<class t_precision = t_type>
447 constexpr t_precision length() const
448 {
449 return ray().template magnitude<t_precision>();
450 }
451
461
462 constexpr t_type lengthSquared() const
463 {
464 return ray().magnitudeSquared();
465 }
466
467
468
483 template<class t_precision = t_type>
484 constexpr Vector<t_dims, t_precision> intersection(const LineSegment& r, t_precision epsilon = 0) const
485 {
486 LineSegment<t_dims, t_precision> line = closestPoints<t_precision>(r);
487 if(abs(line.vertex(B) - line.vertex(A)) <= epsilon)
488 return line.vertex(B);
489 else
490 return Vector<t_dims, t_type>(Constant<t_type>::Invalid);
491 }
492
505 template<class t_precision = t_type>
506 constexpr t_precision intersectionPosition(const LineSegment<t_dims, t_type>& segment) const
507 {
508 Vector<t_dims, t_precision> intersection_location(intersection<t_precision>(segment));
509 if(IsValid(intersection_location))
510 return closestPos(intersection_location);
511 return Constant<t_precision>::Invalid;
512 }
513
528 template<class t_precision = t_type>
529 [[nodiscard]] constexpr bool intersects(const LineSegment<3, t_type>& segment, t_precision epsilon = cast<t_precision>(1e-9)) const
530 {
531 return closestPoints<t_precision>(segment).lengthSquared() <= epsilon;
532 }
533 template<class t_precision = t_type, class t_vertex_type>
534 [[nodiscard]] constexpr bool intersects(const LineSegment<2, t_type, t_vertex_type>& a, t_precision epsilon = cast<t_precision>(1e-9)) const
535 {
536 const Vector<2, t_precision> p = a[A].template as<2, t_precision>();
537 const Vector<2, t_precision> r = a[B].template as<2, t_precision>() - p;
538 const Vector<2, t_precision> q = (*this)[A].template as<2, t_precision>();
539 const Vector<2, t_precision> s = (*this)[B].template as<2, t_precision>() - q;
540
541 const t_precision rxs = cross<t_type>(r, s);
542 const Vector<2, t_precision> qp = q - p;
543 const t_precision qpxr = cross<t_type>(qp, r);
544
545 const t_precision zero = t_precision(0);
546
547 // If r x s == 0 and (q - p) x r == 0, then the lines are colinear
548 if (abs(rxs) <= epsilon && abs(qpxr) <= epsilon)
549 {
550 const t_precision rr = dot(r, r);
551 const t_precision t0 = dot(qp, r) / rr;
552 const t_precision t1 = t0 + dot(s, r) / rr;
553 const t_precision tmin = getMin(t0, t1);
554 const t_precision tmax = getMin(t0, t1);
555 return tmax >= zero && tmin <= t_precision(1);
556 }
557
558 // If r x s == 0 and (q - p) x r != 0, then the lines are parallel and non-intersecting
559 if (abs(rxs) <= epsilon)
560 return false;
561
562 // Otherwise, check if intersection point lies on both segments
563 const t_precision t = cross<t_type>(qp, s) / rxs;
564 const t_precision u = qpxr / rxs;
565
566 return (t >= -epsilon && t <= t_precision(1) + epsilon &&
567 u >= -epsilon && u <= t_precision(1) + epsilon);
568 }
582 template<bool t_clip, class t_precision>
583 constexpr t_precision getLocationAt(t_precision value, uint01 dim) const
584 {
585 if (vertex(A)[dim] == vertex(B)[dim])
586 return Constant<t_precision>::Invalid;
587 if (t_clip)
588 {
589 if (vertex(A)[dim] > vertex(B)[dim])
590 {
591 if (value >= vertex(A)[dim])
592 return cast<t_precision>(0);
593 else if (value <= vertex(B)[dim])
594 return cast<t_precision>(1);
595 }
596 else
597 {
598 if (value >= vertex(B)[dim])
599 return cast<t_precision>(1);
600 else if (value <= vertex(A)[dim])
601 return cast<t_precision>(0);
602 }
603 }
604 return (vertex(A)[dim] - value) / ((value - vertex(B)[dim]) + (vertex(A)[dim] - value));
605 }
606
607
623 template<bool t_clip, class t_precision>
624 constexpr t_vertex pointAt(t_precision value, uint01 dim, const t_vertex& nan_return = Constant<t_vertex>::Invalid) const
625 {
626 if (vertex(A)[dim] == vertex(B)[dim])
627 return nan_return;
628 if (t_clip)
629 {
630 if (vertex(A)[dim] > vertex(B)[dim])
631 {
632 if (value >= vertex(A)[dim])
633 return vertex(A);
634 else if (value <= vertex(B)[dim])
635 return vertex(B);
636 }
637 else
638 {
639 if (value >= vertex(B)[dim])
640 return vertex(B);
641 else if (value <= vertex(A)[dim])
642 return vertex(A);
643 }
644 }
645 const t_precision dt = vertex(A)[dim] - value;
646 const t_precision dy = value - vertex(B)[dim];
647 return (vertex(B) * dt + vertex(A) * dy) / (dt + dy);
648 }
649
650
651
667 template<class t_buffer_type>
668 constexpr static LineSegment createBestFitLine(const t_buffer_type& vertices, uint01 dim_0, uint01 dim_1)
669 {
670 if(vertices.size() < 2)
671 return Constant<LineSegment>::Invalid;
672 if(vertices.size() == 2)
673 return LineSegment(vertices[0], vertices[1]);
674
675 t_vertex total_vector(0);
676 t_type total_volume = 0;
677 t_type total_x_sqr = 0;
678 for(uint04 i = 0; i < vertices.size(); i++)
679 {
680 total_vector += vertices[i];
681 total_x_sqr += vertices[i][dim_0] * vertices[i][dim_0];
682 total_volume += vertices[i][dim_0] * vertices[i][dim_1];
683 }
684
685 const t_type x_sqr = total_vector[dim_0] * total_vector[dim_0];
686 const t_type a = (total_vector[dim_1] * total_x_sqr - total_vector[dim_0] * total_volume) / (vertices.size() * total_x_sqr - x_sqr);
687
688 const t_type b = (vertices.size() * total_volume - total_vector[dim_0] * total_vector[dim_1]) / (vertices.size() * total_x_sqr - x_sqr);
689
690 const t_vertex p1(vertices[0]);
691 const t_vertex p2 = vertices.getLast();
692 p1[dim_1] = a + b * p1[dim_0];
693 p2[dim_1] = a + b * p2[dim_0];
694
695 return LineSegment(p1, p2);
696 }
697 };
698
715 template<uint01 t_dims, class t_type, class t_vertex>
716 constexpr t_type distanceSquaredOptimized(const LineSegment<t_dims, t_type, t_vertex>& line, const t_vertex& vertex, const t_vertex& ray, const t_type& dot_ray)
717 {
718 const t_vertex v_t(vertex - line.vertex(A));
719 const t_type t = dot(v_t, ray);
720 if (t <= 0)
721 return v_t.magnitudeSquared();
722 else if (t >= dot_ray)
723 return distanceSquared(vertex, line.vertex(B));
724 else
725 {
726 t_vertex vc = (ray * t) / dot_ray + line.vertex(A);
727 return distanceSquared(vertex, vc);
728 }
729 }
730
744 template<uint01 t_dims, class t_type, class t_vertex>
745 t_type distanceSquared(const LineSegment<t_dims, t_type, t_vertex>& line, const t_vertex& vertex)
746 {
747 const t_vertex ray_value(line.ray());
748 const t_type dot_ray = dot(ray_value, ray_value);
749 return distanceSquaredOptimized(line, vertex, ray_value, dot_ray);
750 }
751
752
767 template<uint01 t_dims, class t_type, class t_vertex>
768 constexpr t_type distanceSquared(const t_vertex& vertex, const LineSegment<t_dims, t_type, t_vertex>& line)
769 {
770 return distanceSquared(line, vertex);
771 }
772
773
774
790 template<uint01 t_dims, class t_type, class t_vertex>
791 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))
792 {
793 if (equals(left[A], right[A], epsilon))
794 {
795 return (equals(left[B], right[B], epsilon));
796 }
797 if (equals(left[B], right[A], epsilon))
798 {
799 return (equals(left[A], right[B], epsilon));
800 }
801 return false;
802 }
803
804
805
806
807
808 template<uint01 t_dims, class t_type>
809 static constexpr bool IsInvalid(const LineSegment<t_dims, t_type>& value)
810 {
811 for (uint01 dim = 0; dim < 2; ++dim)
812 {
813 if (IsInvalid(value[dim]))
814 return true;
815 }
816 return false;
817 }
818 template<uint01 t_dims, class t_type>
819 static constexpr bool IsValid(const LineSegment<t_dims, t_type>& value)
820 {
821 for (uint01 dim = 0; dim < 2; ++dim)
822 {
823 if (IsInvalid(value[dim]))
824 return false;
825 }
826 return true;
827 }
828 template<uint01 t_dims, class t_type, class t_vector>
829 struct Constant<LineSegment<t_dims, t_type, t_vector>>
830 {
831 constexpr const static LineSegment<t_dims, t_type> Invalid{ Constant<t_vector>::Invalid, Constant<t_vector>::Invalid };
832 constexpr const static LineSegment<t_dims, t_type> Min{ Constant<t_vector>::Min, Constant<t_vector>::Min };
833 constexpr const static LineSegment<t_dims, t_type> Max{ Constant<t_vector>::Max, Constant<t_vector>::Max };
834 };
835
836};
837
Class: LineSegment.
Definition Line.hpp:52
constexpr t_vertex closestValue(const t_vertex &p) const
Definition Line.hpp:377
constexpr LineSegment< t_dims, t_type > scale(const t_inter_type &scale) const
Scales.
Definition Line.hpp:417
constexpr LineSegment< t_new_dims, t_new_type, t_new_vertex > as() const
Definition Line.hpp:73
constexpr t_type lengthSquared() const
Definition Line.hpp:462
constexpr t_precision getLocationAt(t_precision value, uint01 dim) const
Definition Line.hpp:583
constexpr Vector< t_dims, t_precision > intersection(const LineSegment &r, t_precision epsilon=0) const
Intersections.
Definition Line.hpp:484
constexpr t_precision intersectionPosition(const LineSegment< t_dims, t_type > &segment) const
Definition Line.hpp:506
constexpr const t_vertex & vertex(uint01 index) const
Definition Line.hpp:155
constexpr t_type closestPos(const t_vertex &p) const
Returns the closest value where 0 is.
Definition Line.hpp:348
static constexpr LineSegment createBestFitLine(const t_buffer_type &vertices, uint01 dim_0, uint01 dim_1)
Creates best fit line.
Definition Line.hpp:668
constexpr bool isCollinear(const t_vertex &vert, t_precision epsilon=t_precision(1e-10)) const
Query if the line is collinear with the given vertex.
Definition Line.hpp:234
constexpr t_vertex ray() const
Definition Line.hpp:123
constexpr t_precision length() const
Definition Line.hpp:447
constexpr LineSegment< t_dims, t_precision > closestPoints(const LineSegment< t_dims, t_type, t_other_vertex > &l2, t_precision epsilon=0) const
Closest vertices.
Definition Line.hpp:258
constexpr t_vertex pointAt(t_inter_type index) const
Definition Line.hpp:91
constexpr t_vertex midpoint() const
Gets the midpoint.
Definition Line.hpp:106
constexpr t_vertex & vertex(uint01 index)
Definition Line.hpp:172
constexpr t_vertex pointAt(t_precision value, uint01 dim, const t_vertex &nan_return=Constant< t_vertex >::Invalid) const
Point at.
Definition Line.hpp:624
constexpr bool isParallel(const LineSegment< t_dims, t_type, t_vertex > &line, t_precision epsilon=0) const
Query if 'line' is parallel.
Definition Line.hpp:192
constexpr t_vertex center() const
Definition Line.hpp:138
constexpr bool isCollinear(const LineSegment< t_dims, t_type > &line, t_precision epsilon=0) const
Query if 'line' is collinear.
Definition Line.hpp:214
constexpr bool intersects(const LineSegment< 3, t_type > &segment, t_precision epsilon=cast< t_precision >(1e-9)) const
Query if this object intersects the given segment.
Definition Line.hpp:529
A fixed-size array with N dimensions used as the basis for geometric and mathematical types.
Definition Vector.hpp:62
constexpr t_type sum() const
Definition Vector.hpp:527
constexpr Vector< t_dims, t_norm_type > normalized(Vector< t_dims, t_norm_type > value_if_nan=Constant< Vector< t_dims, t_norm_type > >::Invalid) const
Definition Vector.hpp:486
constexpr t_type magnitudeSquared() const
Vectors are commonly used to model forces such as wind, sea current, gravity, and electromagnetism.
Definition Vector.hpp:448
constexpr t_type & operator[](uint01 dimension_index)
Accesses the value of a certain dimension.
Definition Vector.hpp:548
constexpr t_magnitude_type magnitude() const
Vectors are commonly used to model forces such as wind, sea current, gravity, and electromagnetism.
Definition Vector.hpp:470
The primary namespace for the NDEVR SDK.
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator Author: Tyler Parke Date: 2017-11-05...
constexpr t_type getMax(const t_type &left, const t_type &right)
Finds the max of the given arguments using the > operator The only requirement is that t_type have > ...
static constexpr bool IsValid(const Angle< t_type > &value)
Checks whether the given Angle holds a valid value.
Definition Angle.h:398
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...
constexpr Vector< 1, t_type > cross(const Vector< 1, t_type > &, const Vector< 1, t_type > &)
constexpr t_type distanceSquaredOptimized(const LineSegment< t_dims, t_type, t_vertex > &line, const t_vertex &vertex, const t_vertex &ray, const t_type &dot_ray)
Distance squared optimized.
Definition Line.hpp:716
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
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_type clip(const t_type &value, const t_type &lower_bound, const t_type &upper_bound)
Clips the value given so that that the returned value falls between upper and lower bound.
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...