33#include <NDEVR/Triangle.h>
34#include <NDEVR/Bounds.h>
35#include <NDEVR/LineSegment.h>
36#include <NDEVR/Vector.h>
37#include <NDEVR/Polygon.h>
38#include <NDEVR/Plane.h>
63 template<u
int01 t_dims,
class t_type,
class t_vertex>
86 template<u
int01 t_dims,
class t_type,
class t_vertex>
87 static LineSegment<t_dims, t_type> intersection(
const Bounds<t_dims, t_type, t_vertex>& bounds,
const LineSegment<t_dims, t_type, t_vertex>& line)
89 LineSegment<t_dims, t_type> intersected_line = line;
90 for (
uint01 dim = 0; dim < t_dims; ++dim)
92 if (intersected_line.vertex(
A)[dim] < bounds[
MIN][dim])
94 if (intersected_line.vertex(
B)[dim] < bounds[
MIN][dim])
95 return Constant<LineSegment<t_dims, t_type>>
::Invalid;
97 intersected_line.vertex(
A) = line.template pointAt<true>(bounds[
MIN][dim], dim);
99 else if (intersected_line.vertex(
B)[dim] < bounds[
MIN][dim])
101 intersected_line.vertex(
B) = line.template pointAt<true>(bounds[
MIN][dim], dim);
103 if (intersected_line.vertex(
A)[dim] > bounds[
MAX][dim])
105 if (intersected_line.vertex(
B)[dim] > bounds[
MAX][dim])
106 return Constant<LineSegment<t_dims, t_type>>
::Invalid;
108 intersected_line.vertex(
A) = line.template pointAt<true>(bounds[
MAX][dim], dim);
110 else if (intersected_line.vertex(
B)[dim] > bounds[
MAX][dim])
112 intersected_line.vertex(
B) = line.template pointAt<true>(bounds[
MAX][dim], dim);
115 return intersected_line;
134 template<u
int01 t_dims,
class t_type,
class t_vertex>
135 static t_vertex intersection(
const Triangle<t_dims, t_type, t_vertex>& tri,
const LineSegment<t_dims, t_type, t_vertex>& line, t_type epsilon = 0)
137 const t_vertex tri_edge_ab(tri.edge(
A,
B).ray());
138 const t_vertex tri_edge_ca(tri.edge(
A,
C).ray());
139 const t_vertex line_ray(line.ray().template normalized<t_type>());
140 const t_vertex cross_line_tri =
cross(line_ray, tri_edge_ca);
141 const t_type determinant =
dot(tri_edge_ab, cross_line_tri);
142 if (
abs(determinant) < epsilon)
145 const t_vertex t = line.vertex(
A) - tri.vertex(
A);
146 const t_type u0 =
dot(t, cross_line_tri) / determinant;
149 const t_vertex q =
cross(t, tri_edge_ab);
150 const t_type v =
dot(line_ray, q) / determinant;
154 const t_type final_t =
dot(tri_edge_ca, q) / determinant;
155 if (final_t > epsilon && final_t * final_t < line.lengthSquared())
156 return final_t * line_ray + line.vertex(
A);
179 template<u
int01 t_dims,
class t_type,
class t_vertex>
180 static LineSegment<t_dims, t_type, t_vertex> intersection(
const Triangle<t_dims, t_type, t_vertex>& tri_a,
const Triangle<t_dims, t_type, t_vertex>& tri_b, t_type epsilon = 0)
183 const t_vertex normal_a = tri_a.template normal<true>();
184 const t_vertex normal_b = tri_b.template normal<true>();
185 if (normal_a == normal_b)
186 return Constant<LineSegment<t_dims, t_type, t_vertex>>
::Invalid;
187 const t_type dot_1a =
dot(normal_b, tri_a.vertex(
A) - tri_b.vertex(
A));
188 const t_type dot_1b =
dot(normal_b, tri_a.vertex(
B) - tri_b.vertex(
A));
189 const t_type dot_1c =
dot(normal_b, tri_a.vertex(
C) - tri_b.vertex(
A));
190 if ((dot_1a > 0 && dot_1b > 0 && dot_1c > 0) || (dot_1a < 0 && dot_1b < 0 && dot_1c < 0))
191 return Constant<LineSegment<t_dims, t_type, t_vertex>>
::Invalid;
193 if (dot_1a == 0 || dot_1b == 0 || dot_1c == 0)
195 return Constant<LineSegment<t_dims, t_type, t_vertex>>
::Invalid;
197 const t_type dot_2a =
dot(normal_a, tri_b.vertex(
A) - tri_a.vertex(
A));
198 const t_type dot_2b =
dot(normal_a, tri_b.vertex(
B) - tri_a.vertex(
A));
199 const t_type dot_2c =
dot(normal_a, tri_b.vertex(
C) - tri_a.vertex(
A));
201 if ((dot_2a > 0 && dot_2b > 0 && dot_2c > 0) || (dot_2a < 0 && dot_2b < 0 && dot_2c < 0))
202 return Constant<LineSegment<t_dims, t_type, t_vertex>>
::Invalid;
204 if (dot_2a == 0 || dot_2b == 0 || dot_2c == 0)
205 return Constant<LineSegment<t_dims, t_type, t_vertex>>
::Invalid;
207 const t_vertex seg_a1(tri_a.vertex(
A) + (tri_a.vertex(
B) - tri_a.vertex(
A)) * (dot_1a / (dot_1a - dot_1b)));
208 const t_vertex seg_a2(tri_a.vertex(
A) + (tri_a.vertex(
C) - tri_a.vertex(
A)) * (dot_1a / (dot_1a - dot_1c)));
210 const t_vertex seg_b1(tri_b.vertex(
A) + (tri_b.vertex(
B) - tri_b.vertex(
A)) * (dot_2a / (dot_2a - dot_2b)));
211 const t_vertex seg_b2(tri_b.vertex(
A) + (tri_b.vertex(
C) - tri_b.vertex(
A)) * (dot_2a / (dot_2a - dot_2c)));
213 const t_vertex cross_normal =
cross(normal_a, normal_b).template normalized<t_type>();
215 const t_type tp13 =
dot(seg_a2 - seg_a1, cross_normal);
219 const t_type tq12 =
dot(seg_b1 - seg_a1, cross_normal);
220 const t_type tq13 =
dot(seg_b2 - seg_a1, cross_normal);
222 const t_type Iq1 =
getMin(tq12, tq13);
223 const t_type Iq2 =
getMax(tq12, tq13);
226 if (
abs(Ip1 - Iq1) * 2 < ((Ip2 - Ip1) + (Iq2 - Iq1)))
228 t_type n_b =
getMax(Ip1, Iq1);
229 t_type n_a =
getMin(Ip2, Iq2);
232 return LineSegment<t_dims, t_type, t_vertex>(seg_a1 + cross_normal * n_a, seg_a1 + cross_normal * n_b);
235 return Constant<LineSegment<t_dims, t_type, t_vertex>>
::Invalid;
256 template<u
int01 t_dims,
class t_type,
class t_vertex>
257 static LineSegment<t_dims, t_type, t_vertex> intersection(
const Triangle<t_dims, t_type, t_vertex>& tri_a,
const Plane<t_dims, t_type>& plane, t_type epsilon = 0)
260 const t_type signed_dist_a = plane.distanceTo(tri_a.vertex(
A));
261 const t_type signed_dist_b = plane.distanceTo(tri_a.vertex(
B));
262 const t_type signed_dist_c = plane.distanceTo(tri_a.vertex(
C));
263 LineSegment<t_dims, t_type, t_vertex> seg = Constant<LineSegment<t_dims, t_type, t_vertex>>
::Invalid;
266 if (signed_dist_a == 0.0)
268 if (signed_dist_b == 0.0)
270 if (signed_dist_c != 0.0)
272 seg[
A] = tri_a.vertex(
A);
273 seg[
B] = tri_a.vertex(
B);
277 else if (signed_dist_c == 0.0)
279 seg[
A] = tri_a.vertex(
A);
280 seg[
B] = tri_a.vertex(
C);
285 seg[seg_location++] = tri_a.vertex(
A);
288 if (signed_dist_b == 0.0)
290 if (signed_dist_c == 0.0)
292 seg[
A] = tri_a.vertex(
B);
293 seg[
B] = tri_a.vertex(
C);
296 seg[seg_location++] = tri_a.vertex(
B);
298 if (signed_dist_c == 0.0)
300 seg[seg_location++] = tri_a.vertex(
C);
302 if (signed_dist_a * signed_dist_b < 0)
304 t_type t = signed_dist_a / (signed_dist_a - signed_dist_b);
305 seg[seg_location++] = tri_a.vertex(
A) + t * (tri_a.vertex(
B) - tri_a.vertex(
A));
307 if (signed_dist_b * signed_dist_c < 0)
309 t_type t = signed_dist_b / (signed_dist_b - signed_dist_c);
310 seg[seg_location++] = tri_a.vertex(
B) + t * (tri_a.vertex(
C) - tri_a.vertex(
B));
312 if (signed_dist_c * signed_dist_a < 0)
314 t_type t = signed_dist_c / (signed_dist_c - signed_dist_a);
315 seg[seg_location++] = tri_a.vertex(
C) + t * (tri_a.vertex(
A) - tri_a.vertex(
C));
319 template<u
int01 t_dims,
class t_type,
class t_vertex>
320 static LineSegment<t_dims, t_type, t_vertex> intersection(
const Plane<t_dims, t_type>& plane,
const Triangle<t_dims, t_type, t_vertex>& tri_a, t_type epsilon = 0)
322 return intersection(tri_a, plane, epsilon);
328 template<u
int01 t_dims,
class t_type>
336 template<u
int01 t_dims,
class t_type,
class t_vertex>
357 template<u
int01 t_dims,
class t_type,
class t_vertex>
380 template<u
int01 t_dims,
class t_type,
class t_vertex>
388 template<
class t_type,
class t_vertex>
397 template<u
int01 t_dims,
class t_type,
class t_vertex>
406 template<u
int01 t_dims,
class t_type,
class t_vertex>
434 template<u
int01 t_dims,
class t_type,
class t_vertex>
440 t_vertex dir = line.
ray().template normalized<t_type>();
442 t_type det =
dot(edge_ba, pvec);
445 if (
abs(det) < epsilon)
450 t_type u =
dot(tvec, pvec) * invDet;
454 t_vertex qvec(
cross(tvec, edge_ba));
455 t_type v =
dot(dir, qvec) * invDet;
478 template<u
int01 t_dims,
class t_type,
class t_vertex>
483 template<u
int01 t_dims,
class t_type,
class t_vertex>
486 return polygon.template contains<t_type>(line.template as<2, t_type>());
490 template<u
int01 t_dims,
class t_type,
class t_vertex>
497 template<u
int01 t_dims,
class t_type,
class t_vertex>
504 template<u
int01 t_dims,
class t_type,
class t_vertex>
509 if (position_a == position_b)
518 template<u
int01 t_dims,
class t_type,
class t_vertex>
523 if (position_a == position_b)
535 template<u
int01 t_dims,
class t_type,
class t_vertex>
556 template<u
int01 t_dims,
class t_type,
class t_vertex>
564 template<u
int01 t_dims,
class t_type,
class t_vertex>
567 return polygon.template contains<t_type>(tri.template as<2, t_type>());
569 template<u
int01 t_dims,
class t_type,
class t_vertex>
575 if (position_a == position_b && position_a == position_c)
584 template<u
int01 t_dims,
class t_type,
class t_vertex>
590 if (position_a == position_b && position_a == position_c)
616 template<u
int01 t_dims,
class t_type,
class t_vertex>
638 template<u
int01 t_dims,
class t_type,
class t_vertex>
646 for (
uint01 i = 0; i < t_dims; ++i)
671 template<u
int01 t_dims,
class t_type,
class t_vertex>
680 for (
uint01 i = 0; i < t_dims; i++)
682 if (min[i] > bounds[
MAX][i] || max[i] < bounds[
MIN][i])
687 const t_vertex bounds_center(bounds.
center());
689 t_vertex(tri.
vertex(
A) - bounds_center)
690 , t_vertex(tri.
vertex(
B) - bounds_center)
691 , t_vertex(tri.
vertex(
C) - bounds_center));
693 const t_vertex edge[3] = { centered_tri.
edge(
A,
B).ray(), centered_tri.
edge(
B,
C).ray(), centered_tri.
edge(
C,
A).ray() };
694 for (
uint01 edge_index = 0; edge_index < 3; ++edge_index)
696 const t_vertex cur_edge = edge[edge_index];
697 const t_vertex abs_edge =
abs(edge[edge_index]);
698 for (
uint01 i = 0; i < 3; ++i)
706 val_a = cur_edge[
Z] * centered_tri.
vertex(
A)[
Y] - cur_edge[
Y] * centered_tri.
vertex(
A)[
Z];
707 val_b = cur_edge[
Z] * centered_tri.
vertex(
C)[
Y] - cur_edge[
Y] * centered_tri.
vertex(
C)[
Z];
708 radius = abs_edge[
Z] * half_span[
Y] + abs_edge[
Y] * half_span[
Z];
711 val_a = -cur_edge[
Z] * centered_tri.
vertex(
A)[
X] + cur_edge[
X] * centered_tri.
vertex(
A)[
Z];
712 val_b = -cur_edge[
Z] * centered_tri.
vertex(
C)[
X] + cur_edge[
X] * centered_tri.
vertex(
C)[
Z];
713 radius = abs_edge[
Z] * half_span[
X] + abs_edge[
X] * half_span[
Z];
717 val_a = cur_edge[
Y] * centered_tri.
vertex(
B)[
X] - cur_edge[
X] * centered_tri.
vertex(
B)[
Y];
718 val_b = cur_edge[
Y] * centered_tri.
vertex(
C)[
X] - cur_edge[
X] * centered_tri.
vertex(
C)[
Y];
719 radius = abs_edge[
Y] * half_span[
X] + abs_edge[
X] * half_span[
Y];
724 if (val_a > radius || val_b < -radius)
729 if (val_b > radius || val_a < -radius)
734 const t_vertex normal =
cross(edge[0], edge[1]);
737 for (
uint01 i = 0; i < 3; i++)
739 t_type vertex_a_val = centered_tri.
vertex(
A)[i];
742 vertex_min[i] = -half_span[i] - vertex_a_val;
743 vertex_max[i] = half_span[i] - vertex_a_val;
747 vertex_min[i] = half_span[i] - vertex_a_val;
748 vertex_max[i] = -half_span[i] - vertex_a_val;
770 template<u
int01 t_dims,
class t_type,
class t_vertex>
773 bool is_inside =
true;
774 for (
uint01 dim = 0; dim < t_dims; ++dim)
776 if (!(right[
MIN][dim] >= left[
MIN][dim]))
778 if (!(right[
MAX][dim] >= left[
MIN][dim]))
782 if (!(right[
MAX][dim] <= left[
MAX][dim]))
784 if (!(right[
MIN][dim] <= left[
MAX][dim]))
808 template<u
int01 t_dims,
class t_type,
class t_vertex>
811 const t_vertex center = radial.
center();
816 for (
uint01 dim = 0; dim < t_dims; ++dim)
818 if (center[dim] < bounds[
MIN][dim])
819 sqr_dist += (bounds[
MIN][dim] - center[dim]) * (bounds[
MIN][dim] - center[dim]);
820 else if (center[dim] > bounds[
MAX][dim])
821 sqr_dist += (center[dim] - bounds[
MAX][dim]) * (center[dim] - bounds[
MAX][dim]);
822 else if (center[dim] >= bounds[
MIN] + radial.
radius() && center[dim] <= bounds[
MAX][dim] - radial.
radius())
825 if (inside_dims == t_dims)
834 template<u
int01 t_dims,
class t_type,
class t_vertex>
837 return polygon.template contains<t_type>(bounds.template as<2, t_type>());
841 template<u
int01 t_dims,
class t_type,
class t_vertex>
844 t_vertex c = bounds.
center();
845 t_vertex e = bounds[
MAX] - c;
848 t_type r = (e *
abs(plane.
normal)).sum();
860 template<u
int01 t_dims,
class t_type,
class t_vertex>
881 template<u
int01 t_dims,
class t_type,
class t_vertex>
902 template<u
int01 t_dims,
class t_type,
class t_vertex>
907 for (
uint01 i = 0; i < t_dims; i++)
909 const t_type cir_center = radial.
center()[i];
910 const t_type dist_max = (bounds[
MAX][i] - cir_center) * (bounds[
MAX][i] - cir_center);
911 const t_type dist_min = (bounds[
MIN][i] - cir_center) * (bounds[
MIN][i] - cir_center);
912 if (dist_max > dist_min)
915 if (cir_center < bounds[
MIN][i])
921 if (cir_center > bounds[
MAX][i])
925 const t_type rad_squared = radial.
radius() * radial.
radius();
926 if (max_tot < rad_squared)
928 if (min_tot < rad_squared)
932 template<u
int01 t_dims,
class t_type,
class t_vertex>
935 t_vertex c = radial.
center();
941 template<u
int01 t_dims,
class t_type,
class t_vertex>
947 template<
class t_type,
class t_vertex>
956 template<u
int01 t_dims,
class t_type,
class t_vertex>
959 return polygon.template contains<t_type>(bounds.template as<2, t_type>());
963 template<u
int01 t_dims,
class t_type,
class t_vertex>
966 return polygon.template contains<t_type>(tri.template as<2, t_type>());
970 template<u
int01 t_dims,
class t_type,
class t_vertex>
973 return polygon.template contains<t_type>(line.template as<2, t_type>());
#define UNUSED(expr)
Definition BaseValues.hpp:409
A specification of upper and lower bounds in N-dimensions.
Definition Bounds.hpp:52
constexpr Ray< t_dims, t_type > span() const
The side lengths of these bounds. For each dimension, the span is max - min.
Definition Bounds.hpp:111
constexpr bool contains(const t_type &value) const
Query if this object contains the given value. t_allow_bounds - whether or not to allow boundary case...
Definition Bounds.hpp:237
constexpr t_vertex center() const
Returns the center of the bounds.
Definition Bounds.hpp:120
constexpr bool doesIntersect(t_type distance_a, t_type distance_b, const t_vertex &origin, const Vector< t_dims, t_type > &ray, uint01 exclusion_axis) const
Checks for intersection of the ray from a given distance, excluding one axis.
Definition Bounds.hpp:577
Dummy class for including intersection functions.
Definition Intersection.hpp:45
A line segment represented by two vertices, a start and end.
Definition Line.hpp:49
constexpr t_vertex ray() const
Definition Line.hpp:120
constexpr const t_vertex & vertex(uint01 index) const
Definition Line.hpp:152
constexpr t_type lengthSquared() const
Definition Line.hpp:463
Logic for a given plane or N-dimensions. Planes are coordinate systems of one less dimension than the...
Definition Geometry.h:41
t_type d
Definition Plane.hpp:223
t_type distanceTo(const Vector< t_dims, t_type > &pos) const
Definition Plane.hpp:110
PlanePosition planePosition(const Vector< t_dims, t_type > &pos) const
Definition Plane.hpp:88
Ray< t_dims, t_type > normal
Definition Plane.hpp:222
bool contains(const Vector< 3, t_type > &point, t_type epsilon) const
Definition Plane.hpp:202
An N-sided polygon.
Definition Polygon.hpp:53
bool contains(const Vertex< 2, t_type > &vector) const
Definition Polygon.hpp:478
A radial object.
Definition RadialObject.hpp:52
constexpr t_type radius() const
Definition RadialObject.hpp:123
constexpr const t_vertex & center() const
Definition RadialObject.hpp:152
constexpr bool contains(const t_vertex &vector) const
Definition RadialObject.hpp:105
A triangle is a polygon with three edges and three vertices. It is one of the basic shapes in geometr...
Definition Triangle.hpp:138
constexpr bool contains(const Vector< t_dims - 1, t_type > &p) const
Definition Triangle.hpp:443
constexpr t_vertex & vertex(TriangleLocation triangle_node)
Vertices the given triangle node.
Definition Triangle.hpp:168
constexpr LineSegment< t_dims, t_type, t_vertex > edge(uint01 triangle_node_a, uint01 triangle_node_b) const
Definition Triangle.hpp:256
A fixed-size array with better performance compared to dynamic containers.
Definition Vector.hpp:60
A vertex or point. A specific type of Vector used primarily for spacial location information.
Definition Vertex.hpp:48
constexpr bool IsInvalid(const t_type &value)
Query if 'value' is valid or invalid. Invalid values should return invalid if used for calculations o...
Definition BaseFunctions.hpp:170
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 > ...
Definition BaseFunctions.hpp:94
t_type dot(const Vector< t_dims, t_type > &v1, const Vector< t_dims, t_type > &v2)
Definition VectorFunctions.hpp:1030
@ MIN
Definition BaseValues.hpp:196
@ MAX
Definition BaseValues.hpp:197
@ edge_ca
Definition Triangle.hpp:51
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:80
t_type distanceSquared(const Bounds< t_dims, t_type, t_vertex > &bounds, const Vector< t_dims, t_type > &vertex)
Definition Distance.hpp:46
IntersectionTypes
Used for classifying shape intersections.
Definition BaseValues.hpp:210
@ inside
Definition BaseValues.hpp:212
@ mixed
Definition BaseValues.hpp:213
@ outside
Definition BaseValues.hpp:211
constexpr fltp08 intersection_epsilon
Definition Intersection.hpp:46
PlanePosition
The location of an object either below, above, or on a given N-dimensional plane.
Definition Plane.hpp:42
constexpr Vector< 1, t_type > cross(const Vector< 1, t_type > &, const Vector< 1, t_type > &)
Definition VectorFunctions.hpp:898
IntersectionTypes classify(const Vector< t_dims, t_type > &v1, const Vector< t_dims, t_type > &v2)
Definition Intersection.hpp:329
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:375
constexpr Angle< t_angle_type > abs(const Angle< t_angle_type > &value)
Changes an input with a negative sign, to a positive sign.
Definition AngleFunctions.h:645
@ B
Definition BaseValues.hpp:170
@ A
Definition BaseValues.hpp:168
@ Y
Definition BaseValues.hpp:169
@ X
Definition BaseValues.hpp:167
@ C
Definition BaseValues.hpp:172
@ Z
Definition BaseValues.hpp:171
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:149
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...
Definition BaseFunctions.hpp:56
static const t_type Invalid
Definition BaseValues.hpp:234