33#include <NDEVR/BaseValues.h>
34#include <NDEVR/Vertex.h>
35#include <NDEVR/LineSegment.h>
36#include <NDEVR/Angle.h>
37#include <NDEVR/AngleDefinitions.h>
72 case vertex_a:
return edge_bc;
73 case vertex_b:
return edge_ca;
74 case vertex_c:
return edge_ab;
75 case edge_bc:
return vertex_a;
76 case edge_ca:
return vertex_b;
77 case edge_ab:
return vertex_c;
79 lib_assert(
false,
"Segment does not have oposite value");
82 return tri_location_nan;
96 case vertex_a:
return vertex_b;
97 case vertex_b:
return vertex_c;
98 case vertex_c:
return vertex_a;
100 lib_assert(
false,
"Not a valid vertex request");
101 return tri_location_nan;
116 case vertex_a:
return vertex_c;
117 case vertex_b:
return vertex_a;
118 case vertex_c:
return vertex_b;
120 lib_assert(
false,
"Not a valid vertex request");
121 return tri_location_nan;
140 template<u
int01 t_dims,
class t_type,
class t_vertex = Vertex<t_dims, t_type>>
146 explicit constexpr Triangle(
const t_type& a)
147 : Vector<3, t_vertex>(t_vertex(a), t_vertex(a), t_vertex(a))
149 constexpr Triangle(
const t_type& a,
const t_type& b,
const t_type& c)
150 : Vector<3, t_vertex>(t_vertex(a), t_vertex(b), t_vertex(c))
152 explicit constexpr Triangle(
const t_vertex& vector)
153 : Vector<3, t_vertex>(vector)
155 constexpr Triangle(
const t_vertex& a,
const t_vertex& b,
const t_vertex& c)
156 : Vector<3, t_vertex>(a, b, c)
174 switch (triangle_node)
176 case vertex_a:
return vertex(A);
177 case vertex_b:
return vertex(B);
178 case vertex_c:
return vertex(C);
179 default: lib_assert(
false,
"Not a valid vertex request");
return vertex(A);
198 switch (triangle_node)
200 case vertex_a:
return vertex(A);
201 case vertex_b:
return vertex(B);
202 case vertex_c:
return vertex(C);
203 default: lib_assert(
false,
"Not a valid vertex request");
return vertex(A);
222 lib_assert(triangle_node <= 2,
"Tried to access bad Triangle Node");
223 return (*
this)[triangle_node];
239 [[nodiscard]]
constexpr const t_vertex&
vertex(
uint01 triangle_node)
const
241 lib_assert(triangle_node <= 2,
"Tried to access bad Triangle Node");
242 return (*
this)[triangle_node];
262 lib_assert(triangle_node_a <= 2 && triangle_node_b <= 2,
"Tried to access bad Triangle Node");
302 template<
class t_angle_type>
305 lib_assert(triangle_node <= 2,
"Tried to access bad Triangle Node");
306 const uint01 left = triangle_node > 0 ? triangle_node - 1 : 2;
307 const uint01 right = triangle_node < 2 ? triangle_node + 1 : 0;
313 lib_assert(triangle_node <= 2,
"Tried to access bad Triangle Node");
314 uint01 left = triangle_node > 0 ? triangle_node - 1 : 2;
315 uint01 right = triangle_node < 2 ? triangle_node + 1 : 0;
323 return (y *
sqrt(1.0 - ((x * x) / (y * y)))) / x;
338 template<
class t_angle_type>
360 template<
class t_area_type>
361 [[nodiscard]]
constexpr inline t_area_type
area()
const
391 [[nodiscard]]
constexpr t_vertex
center()
const
408 template<u
int01 t_new_dims,
class t_new_type>
409 [[nodiscard]]
constexpr Triangle<t_new_dims, t_new_type>
as()
const
424 template<
bool is_normalized,
class t_normal_type = t_type>
425 [[nodiscard]]
constexpr Vector<t_dims, t_normal_type>
normal()
const
429 Vector<t_dims, t_normal_type> cross_product =
cross(edge1, edge2);
431 return cross_product;
447 [[nodiscard]]
constexpr inline bool contains(
const Vector<t_dims - 1, t_type>& p)
const
479 [[nodiscard]]
constexpr bool contains(
const t_vertex& vertex_point, t_type epsilon = t_type(0.0001))
const
482 for(
uint01 dim = 0; dim < t_dims; dim++)
489 const t_vertex dbp = vertex_point -
vertex(A);
492 t_type dotca =
dot(dca, dca);
493 t_type dotcaba =
dot(dca, dba);
494 t_type dotcabp =
dot(dca, dbp);
495 t_type dotba =
dot(dba, dba);
496 t_type dotbabp =
dot(dba, dbp);
499 t_type invDenom = (dotca * dotba - dotcaba * dotcaba);
500 t_type u = ((dotba * dotcabp) - (dotcaba * dotbabp)) / invDenom;
501 t_type v = ((dotca * dotbabp) - (dotcaba * dotcabp)) / invDenom;
504 if ((u >= 0) && (v >= 0) && (u + v < 1))
510 for (
uint01 location = edge_ab; location <= edge_ca; location++)
535 switch (object_to_check)
542 for (
uint01 i = edge_ab; i <= edge_ca; i++)
545 if (
equals(edge_a, edge_b, epsilon))
548 return tri_location_nan;
554 const t_vertex vertex_1 =
vertex(object_to_check);
555 for (
uint01 i = vertex_a; i <= vertex_c; i++)
558 if (
equals(vertex_1, vertex_2, epsilon))
561 return tri_location_nan;
566 return tri_location_nan;
570 const t_vertex vertex_a =
vertex(object_to_check);
571 for (
uint01 i = 0; i <= 2; i++)
573 t_vertex vertex_b = tri.
vertex(i);
574 if (
equals(vertex_a, vertex_b, epsilon))
577 return tri_location_nan;
580 return tri_location_nan;
600 for (
uint01 i = A; i <= C; ++i)
603 return Constant<uint01>::Invalid;
605 [[nodiscard]]
constexpr TriangleLocation getIdentityOf(
const t_vertex& p)
const
607 for (
uint01 i = A; i <= C; ++i)
610 return tri_location_nan;
612 [[nodiscard]]
constexpr TriangleLocation getIdentityOf(
const t_vertex& p, t_type epsilon)
const
614 lib_assert(
IsValid(p),
"Cannot get triangle identity of Invalid type");
615 for (
uint01 i = A; i <= C; ++i)
618 return tri_location_nan;
620 [[nodiscard]]
constexpr TriangleLocation getIdentityOf(
const LineSegment<t_dims, t_type, t_vertex>& line, t_type epsilon)
const
622 switch (getIdentityOf(line[A], epsilon))
625 switch (getIdentityOf(line[B], epsilon))
627 case vertex_a:
return vertex_a;
628 case vertex_b:
return edge_ab;
629 case vertex_c:
return edge_ca;
630 default:
return tri_location_nan;
633 switch (getIdentityOf(line[B], epsilon))
635 case vertex_a:
return edge_ab;
636 case vertex_b:
return vertex_b;
637 case vertex_c:
return edge_bc;
638 default:
return tri_location_nan;
641 switch (getIdentityOf(line[B], epsilon))
643 case vertex_a:
return edge_ca;
644 case vertex_b:
return edge_bc;
645 case vertex_c:
return vertex_c;
646 default:
return tri_location_nan;
648 default:
return tri_location_nan;
651 [[nodiscard]]
constexpr TriangleLocation getIdentityOf(
const LineSegment<t_dims, t_type, t_vertex>& line)
const
653 switch (getIdentityOf(line[A]))
656 switch (getIdentityOf(line[B]))
658 case vertex_a:
return vertex_a;
659 case vertex_b:
return edge_ab;
660 case vertex_c:
return edge_ca;
661 default:
return tri_location_nan;
664 switch (getIdentityOf(line[B]))
666 case vertex_a:
return edge_ab;
667 case vertex_b:
return vertex_b;
668 case vertex_c:
return edge_bc;
669 default:
return tri_location_nan;
672 switch (getIdentityOf(line[B]))
674 case vertex_a:
return edge_ca;
675 case vertex_b:
return edge_bc;
676 case vertex_c:
return vertex_c;
677 default:
return tri_location_nan;
679 default:
return tri_location_nan;
684 lib_assert(
IsValid(p),
"Cannot get triangle location of Invalid type");
685 for (
uint01 i = A; i <= C; ++i)
688 for(
uint01 location = edge_ab; location <= edge_ca; location++)
692 const t_vertex normal_abp = Triangle(
vertex(A),
vertex(B), p).normal<
true>();
693 const t_vertex normal_bcp = Triangle(
vertex(B),
vertex(C), p).normal<
true>();
695 const t_type dot_1 =
dot(normal_abp, normal_bcp);
696 if(dot_1 >= epsilon + 1 || dot_1 <= -epsilon + 1)
699 const t_vertex normal_cap = Triangle(
vertex(C),
vertex(A), p).normal<
true>();
700 const t_type dot_2 =
dot(normal_bcp, normal_cap);
701 if((dot_2 >= epsilon + 1 && dot_2 <= -epsilon + 1))
706 [[nodiscard]]
constexpr TriangleLocation getLocation(
const LineSegment<t_dims, t_type, t_vertex>& line, t_type epsilon =
cast<t_type>(0))
const
708 switch (getLocation(line[A], epsilon))
711 switch (getLocation(line[B], epsilon))
715 case edge_ab:
return edge_ab;
719 case inside_tri:
return inside_tri;
720 default:
return mixed_location_tri;
723 switch (getLocation(line[B], epsilon))
727 case edge_bc:
return edge_bc;
731 case inside_tri:
return inside_tri;
732 default:
return mixed_location_tri;
735 switch (getLocation(line[B], epsilon))
739 case edge_ca:
return edge_ca;
743 case inside_tri:
return inside_tri;
744 default:
return mixed_location_tri;
747 switch (getLocation(line[B], epsilon))
749 case vertex_c:
return edge_ca;
750 case vertex_b:
return edge_ab;
751 case vertex_a:
return vertex_a;
752 case edge_ca:
return edge_ca;
753 case edge_ab:
return edge_ab;
755 case inside_tri:
return inside_tri;
756 default:
return mixed_location_tri;
759 switch (getLocation(line[B], epsilon))
761 case vertex_b:
return vertex_b;
762 case vertex_c:
return edge_bc;
763 case vertex_a:
return edge_ab;
764 case edge_bc:
return edge_bc;
765 case edge_ab:
return edge_ab;
767 case inside_tri:
return inside_tri;
768 default:
return mixed_location_tri;
771 switch (getLocation(line[B], epsilon))
773 case vertex_c:
return vertex_c;
774 case vertex_b:
return edge_bc;
775 case vertex_a:
return edge_ca;
776 case edge_bc:
return edge_bc;
777 case edge_ca:
return edge_ca;
779 case inside_tri:
return inside_tri;
780 default:
return mixed_location_tri;
783 if (getLocation(line[B], epsilon) == outside_tri)
784 return mixed_location_tri;
788 if (getLocation(line[B], epsilon) == outside_tri)
791 return mixed_location_tri;
793 lib_assert(
false,
"Should never arrive here in triangle identity line");
795 lib_assert(
false,
"Should never arrive here in triangle identity line");
796 return tri_location_nan;
837 bool hasVertex(
const t_vertex& point)
const
860 template<u
int01 t_dims,
class t_type,
class t_vertex>
863 const t_vertex edge0 = tri.
edge(B, A).ray();
864 const t_vertex edge1 = tri.
edge(C, A).ray();
866 const t_type a =
dot(edge0, edge0);
867 const t_type b =
dot(edge0, edge1);
868 const t_type c =
dot(edge1, edge1);
870 const t_type det = a * c - b * b;
872 return ClosestPoint(tri, point, edge0, edge1, a, b, c, det);
874 template<u
int01 t_dims,
class t_type,
class t_vertex>
875 constexpr Vector<t_dims, t_type> ClosestPoint(
const Triangle<t_dims, t_type, t_vertex>& tri,
const t_vertex& point,
const t_vertex& edge0,
const Vector<t_dims, t_type>& edge1, t_type a, t_type b, t_type c, t_type det)
877 const t_vertex v0(tri.vertex(A) - point);
878 const t_type d =
dot(edge0, v0);
879 const t_type e =
dot(edge1, v0);
881 t_type s = b * e - c * d;
882 t_type t = b * d - a * e;
927 t_type numer = tmp1 - tmp0;
928 t_type denom = a - 2 * b + c;
942 t_type numer = c + e - b - d;
943 t_type denom = a - 2 * b + c;
955 t_type numer = c + e - b - d;
956 t_type denom = a - 2 * b + c;
962 return tri.vertex(A) + s * edge0 + t * edge1;
980 template<
bool t_has_winding, u
int01 t_dims,
class t_type,
class t_vertex>
984 for (
uint01 n = A; n <= C; ++n)
995 else if(!t_has_winding && tri_a.
vertex(B) == tri_b.
vertex((C + dif) % 3))
1006 template<u
int01 t_dims,
class t_type,
class t_vector>
1007 struct Constant<Triangle<t_dims, t_type, t_vector>>
1009 constexpr const static Triangle<t_dims, t_type, t_vector>
Invalid{ Constant<t_vector>::Invalid, Constant<t_vector>::Invalid, Constant<t_vector>::Invalid };
1010 constexpr const static Triangle<t_dims, t_type, t_vector> Min{ Constant<t_vector>::Min, Constant<t_vector>::Min, Constant<t_vector>::Min };
1011 constexpr const static Triangle<t_dims, t_type, t_vector> Max{ Constant<t_vector>::Max, Constant<t_vector>::Max, Constant<t_vector>::Max };
1014 template<u
int01 t_dims,
class t_type>
1017 for (
uint01 dim = 0; dim < t_dims; ++dim)
1024 template<u
int01 t_dims,
class t_type>
1027 for (
uint01 dim = 0; dim < t_dims; ++dim)
static Angle< t_angle_type > Rotation(const Vector< t_dims, t_type > &left, const Vector< t_dims, t_type > &middle, const Vector< t_dims, t_type > &right)
Gets a rotation.
Stores an angle in an optimized internal format with support for efficient trigonometric operations.
Base class for N-dimensional triangles.
static constexpr TriangleLocation NextVertexCCW(TriangleLocation location)
Returns the point location counter-clockwise to given point location.
static constexpr TriangleLocation NextVertexCW(TriangleLocation location)
Returns the point location clockwise to given point location.
A three-vertex polygon representing a triangle in N-dimensional space.
constexpr const t_vertex & nextVertexCCW(const t_vertex &point) const
constexpr t_vertex center() const
constexpr const t_vertex & nextVertexCW(const t_vertex &point) const
constexpr const t_vertex & vertex(TriangleLocation triangle_node) const
Vertices the given triangle node.
constexpr t_vertex & vertex(uint01 triangle_node)
constexpr t_vertex & vertex(TriangleLocation triangle_node)
Vertices the given triangle node.
constexpr bool contains(const Vector< t_dims - 1, t_type > &p) const
constexpr Triangle< t_new_dims, t_new_type > as() const
constexpr uint01 vertexIndex(const t_vertex &p) const
constexpr Angle< t_angle_type > angle(uint01 triangle_node) const
constexpr LineSegment< t_dims, t_type, t_vertex > edge(TriangleLocation location) const
Edges the given location.
constexpr Angle< t_angle_type > angle(TriangleLocation location) const
constexpr TriangleLocation sharesObject(TriangleLocation object_to_check, const Triangle< t_dims, t_type, t_vertex > &tri, t_type epsilon=0) const
constexpr t_area_type area() const
constexpr bool contains(const t_vertex &vertex_point, t_type epsilon=t_type(0.0001)) const
constexpr Vector< t_dims, t_normal_type > normal() const
constexpr const t_vertex & vertex(uint01 triangle_node) const
constexpr LineSegment< t_dims, t_type, t_vertex > edge(uint01 triangle_node_a, uint01 triangle_node_b) const
constexpr t_vertex centroid() const
A fixed-size array with N dimensions used as the basis for geometric and mathematical types.
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
Gets the normalized, or unit length representation of this vector.
constexpr t_type magnitudeSquared() const
Vectors are commonly used to model forces such as wind, sea current, gravity, and electromagnetism.
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.
t_type dot(const Vector< t_dims, t_type > &v1, const Vector< t_dims, t_type > &v2)
constexpr HSLColor Constant< HSLColor >::Invalid
The invalid HSLColor constant with all components set to invalid.
double fltp08
Defines an alias representing an 8 byte floating-point number.
TriangleLocation
Values that represent triangle locations.
@ RADIANS
Angle measured in radians (0 to 2*PI for a full circle).
constexpr Vector< 1, t_type > cross(const Vector< 1, t_type > &, const Vector< 1, t_type > &)
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.
t_type sqrt(const t_type &value)
constexpr bool Equals(const Triangle< t_dims, t_type, t_vertex > &tri_a, const Triangle< t_dims, t_type, t_vertex > &tri_b, t_type epsilon=0)
std::enable_if<!ObjectInfo< t_type >::Float, fltp08 >::type tan(const Angle< t_type > &angle)
Performs optimized tangent operation on the given angle using pre-computed lookup table for optimal s...
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.
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.