API Documentation
Loading...
Searching...
No Matches
Triangle.hpp
Go to the documentation of this file.
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: Triangle
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/LineSegment.h>
36#include <NDEVR/Angle.h>
37#include <NDEVR/AngleDefinitions.h>
38
39namespace NDEVR
40{
41 /**--------------------------------------------------------------------------------------------------
42 Enum: TriangleLocation
43
44 \brief Values that represent triangle locations.
45 **/
62 /**--------------------------------------------------------------------------------------------------
63 \brief Base class for N-dimensional triangles
64 **/
66 {
67 public:
69 {
70 switch (location)
71 {
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;
78 default:
79 lib_assert(false, "Segment does not have oposite value");
80 break;
81 }
82 return tri_location_nan;
83 }
84
85 /**--------------------------------------------------------------------------------------------------
86 \brief Returns the point location counter-clockwise to given point location.
87
88 Author: Tyler Parke
89
90 Date: 2017-05-15
91 **/
93 {
94 switch (location)
95 {
96 case vertex_a: return vertex_b;
97 case vertex_b: return vertex_c;
98 case vertex_c: return vertex_a;
99 default:
100 lib_assert(false, "Not a valid vertex request");
101 return tri_location_nan;
102 }
103 }
104
105 /**--------------------------------------------------------------------------------------------------
106 \brief Returns the point location clockwise to given point location.
107
108 Author: Tyler Parke
109
110 Date: 2017-05-15
111 **/
113 {
114 switch (location)
115 {
116 case vertex_a: return vertex_c;
117 case vertex_b: return vertex_a;
118 case vertex_c: return vertex_b;
119 default:
120 lib_assert(false, "Not a valid vertex request");
121 return tri_location_nan;
122 }
123 }
124 };
125
126 /**--------------------------------------------------------------------------------------------------
127 Class: Triangle
128
129 \brief A triangle is a polygon with three edges and three vertices. It is one of the basic shapes in
130 geometry. This triangle with vertices A, B, and C is which can be accessed using vertex(...)
131
132 Author: Tyler Parke
133
134 Date: 2017-11-17
135 **/
136 template<uint01 t_dims, class t_type, class t_vertex = Vertex<t_dims, t_type>>
137 class Triangle : public Vector<3, t_vertex>, public TriangleBase
138 {
139 public:
140 constexpr Triangle()
141 {}
142 explicit constexpr Triangle(const t_type& a)
143 : Vector<3, t_vertex>(t_vertex(a), t_vertex(a), t_vertex(a))
144 {}
145 constexpr Triangle(const t_type& a, const t_type& b, const t_type& c)
146 : Vector<3, t_vertex>(t_vertex(a), t_vertex(b), t_vertex(c))
147 {}
148 explicit constexpr Triangle(const t_vertex& vector)
149 : Vector<3, t_vertex>(vector)
150 {}
151 constexpr Triangle(const t_vertex& a, const t_vertex& b, const t_vertex& c)
152 : Vector<3, t_vertex>(a, b, c)
153 {}
154
155 /**--------------------------------------------------------------------------------------------------
156 \brief Vertices the given triangle node.
157
158 Author: Tyler Parke
159
160 Date: 2017-11-17
161
162 Parameters:
163 triangle_node - The triangle node.
164
165 \returns A reference to a t_vertex.
166 **/
167
168 [[nodiscard]] constexpr t_vertex& vertex(TriangleLocation triangle_node)
169 {
170 switch (triangle_node)
171 {
172 case vertex_a: return vertex(A);
173 case vertex_b: return vertex(B);
174 case vertex_c: return vertex(C);
175 default: lib_assert(false, "Not a valid vertex request"); return vertex(A);
176 }
177 }
178
179 /**--------------------------------------------------------------------------------------------------
180 \brief Vertices the given triangle node.
181
182 Author: Tyler Parke
183
184 Date: 2017-11-17
185
186 Parameters:
187 triangle_node - The triangle node.
188
189 \returns A reference to a const t_vertex.
190 **/
191
192 [[nodiscard]] constexpr const t_vertex& vertex(TriangleLocation triangle_node) const
193 {
194 switch (triangle_node)
195 {
196 case vertex_a: return vertex(A);
197 case vertex_b: return vertex(B);
198 case vertex_c: return vertex(C);
199 default: lib_assert(false, "Not a valid vertex request"); return vertex(A);
200 }
201 }
202
203 /**--------------------------------------------------------------------------------------------------
204 Vertices the given triangle node.
205
206 Author: Tyler Parke
207
208 Date: 2017-11-17
209
210 Parameters:
211 triangle_node - The triangle node.
212
213 \returns A reference to a t_vertex.
214 **/
215
216 [[nodiscard]] constexpr t_vertex& vertex(uint01 triangle_node)
217 {
218 lib_assert(triangle_node <= 2, "Tried to access bad Triangle Node");
219 return (*this)[triangle_node];
220 }
221
222 /**--------------------------------------------------------------------------------------------------
223 Vertices the given triangle node.
224
225 Author: Tyler Parke
226
227 Date: 2017-11-17
228
229 Parameters:
230 triangle_node - The triangle node.
231
232 \returns A reference to a const t_vertex.
233 **/
234
235 [[nodiscard]] constexpr const t_vertex& vertex(uint01 triangle_node) const
236 {
237 lib_assert(triangle_node <= 2, "Tried to access bad Triangle Node");
238 return (*this)[triangle_node];
239 }
240
241 /**--------------------------------------------------------------------------------------------------
242
243 Edges.
244
245 Author: Tyler Parke
246
247 Date: 2017-11-17
248
249 Parameters:
250 triangle_node_a - The triangle node a.
251 triangle_node_b - The triangle node b.
252
253 \returns A LineSegment&lt;t_dims,t_type,t_vertex&gt;
254 **/
255
256 [[nodiscard]] constexpr LineSegment<t_dims, t_type, t_vertex> edge(uint01 triangle_node_a, uint01 triangle_node_b) const
257 {
258 lib_assert(triangle_node_a <= 2 && triangle_node_b <= 2, "Tried to access bad Triangle Node");
259 return LineSegment<t_dims, t_type, t_vertex>((*this)[triangle_node_a], (*this)[triangle_node_b]);
260 }
261
262 /**--------------------------------------------------------------------------------------------------
263 \brief Edges the given location.
264
265 Author: Tyler Parke
266
267 Date: 2017-11-17
268
269 Parameters:
270 location - The location.
271
272 \returns A LineSegment&lt;t_dims,t_type,t_vertex&gt;
273 **/
274
275 [[nodiscard]] constexpr LineSegment<t_dims, t_type, t_vertex> edge(TriangleLocation location) const
276 {
277 switch (location)
278 {
282 default: lib_assert(false, "Not a valid line segment request"); return LineSegment<t_dims, t_type>();
283 }
284 }
285
286 /**--------------------------------------------------------------------------------------------------
287 Angles the given triangle node.
288
289 Author: Tyler Parke
290
291 Date: 2018-11-24
292
293 Parameters:
294 triangle_node - The triangle node.
295
296 \returns An Angle.
297 **/
298 template<class t_angle_type>
299 [[nodiscard]] constexpr Angle< t_angle_type> angle(uint01 triangle_node) const
300 {
301 lib_assert(triangle_node <= 2, "Tried to access bad Triangle Node");
302 const uint01 left = triangle_node > 0 ? triangle_node - 1 : 2;
303 const uint01 right = triangle_node < 2 ? triangle_node + 1 : 0;
304 return AngleDefinitions::Rotation<t_angle_type>(vertex(left), vertex(triangle_node), vertex(right));
305 }
306
307 [[nodiscard]] constexpr fltp08 tan(uint01 triangle_node) const
308 {
309 lib_assert(triangle_node <= 2, "Tried to access bad Triangle Node");
310 uint01 left = triangle_node > 0 ? triangle_node - 1 : 2;
311 uint01 right = triangle_node < 2 ? triangle_node + 1 : 0;
312
313 const Vector<t_dims, t_type> v_left(vertex(left) - vertex(triangle_node));
314 const Vector<t_dims, t_type> v_right(vertex(triangle_node) - vertex(right));
315 fltp08 x = dot(v_left, v_right);
316 fltp08 y = cast<fltp08>(sqrt(v_left.magnitudeSquared() * v_right.magnitudeSquared()));
317
318
319 return (y * sqrt(1.0 - ((x * x) / (y * y)))) / x;
320 }
321
322 /**--------------------------------------------------------------------------------------------------
323 Angles the given location.
324
325 Author: Tyler Parke
326
327 Date: 2017-11-17
328
329 Parameters:
330 location - The location.
331
332 \returns An Angle.
333 **/
334 template<class t_angle_type>
335 [[nodiscard]] constexpr Angle<t_angle_type> angle(TriangleLocation location) const
336 {
337 switch (location)
338 {
339 case angle_a: return angle<t_angle_type>(A);
340 case angle_b: return angle<t_angle_type>(B);
341 case angle_c: return angle<t_angle_type>(C);
342 default: lib_assert(false, "Not a valid vertex request"); return Angle<t_angle_type>(RADIANS, 0.0f);
343 }
344 }
345
346
347 /**--------------------------------------------------------------------------------------------------
348 Gets the area.
349
350 Author: Tyler Parke
351
352 Date: 2017-11-17
353
354 \returns A t_area_type.
355 **/
356 template<class t_area_type>
357 [[nodiscard]] constexpr inline t_area_type area() const
358 {
360 }
361
362 /**--------------------------------------------------------------------------------------------------
363 Gets the centroid.
364
365 Author: Tyler Parke
366
367 Date: 2017-11-17
368
369 \returns A t_vertex.
370 **/
371
372 [[nodiscard]] constexpr t_vertex centroid() const
373 {
374 return ((cast<t_type>(2) * edge(B, C).midpoint()) + vertex(A)) / cast<t_type>(3);
375 }
376
377 /**--------------------------------------------------------------------------------------------------
378 Gets the center.
379
380 Author: Tyler Parke
381
382 Date: 2017-11-17
383
384 \returns A t_vertex.
385 **/
386
387 [[nodiscard]] constexpr t_vertex center() const
388 {
389 t_vertex avg = (vertex(A) + vertex(B) + vertex(C)) / cast<t_type>(3);
390 avg = clip(avg, getMin(vertex(A), vertex(B), vertex(C)), getMax(vertex(A), vertex(B), vertex(C)));
391 return avg;
392 }
393
394
395 /**--------------------------------------------------------------------------------------------------
396 Gets as.
397
398 Author: Tyler Parke
399
400 Date: 2017-11-17
401
402 \returns as.
403 **/
404 template<uint01 t_new_dims, class t_new_type>
409
410
411 /**--------------------------------------------------------------------------------------------------
412 Gets the normal.
413
414 Author: Tyler Parke
415
416 Date: 2017-11-17
417
418 \returns A Vector&lt;t_dims,t_normal_type&gt;
419 **/
420 template<bool is_normalized, class t_normal_type = t_type>
421 [[nodiscard]] constexpr Vector<t_dims, t_normal_type> normal() const
422 {
425 Vector<t_dims, t_normal_type> cross_product = cross(edge1, edge2);
426 if (is_normalized) cross_product = cross_product.template normalized<t_normal_type>();
427 return cross_product;
428 }
429
430 /**--------------------------------------------------------------------------------------------------
431 Query if this object contains the given p.
432
433 Author: Tyler Parke
434
435 Date: 2017-11-17
436
437 Parameters:
438 p - The const Vector&lt;t_dims-1,t_type&gt;&amp; to test for containment.
439
440 \returns True if the object is in this collection, false if not.
441 **/
442
443 [[nodiscard]] constexpr inline bool contains(const Vector<t_dims - 1, t_type>& p) const
444 {
445 if((p[X] - vertex(B)[X]) * (vertex(A)[Y] - vertex(B)[Y]) - (vertex(A)[X] - vertex(B)[X]) * (p[Y] - vertex(B)[Y]) < cast<t_type>(0))
446 {
447 if ((p[X] - vertex(C)[X]) * (vertex(B)[Y] - vertex(C)[Y]) - (vertex(B)[X] - vertex(C)[X]) * (p[Y] - vertex(C)[Y]) >= cast<t_type>(0))
448 return false;
449 if ((p[X] - vertex(A)[X]) * (vertex(C)[Y] - vertex(A)[Y]) - (vertex(C)[X] - vertex(A)[X]) * (p[Y] - vertex(A)[Y]) >= cast<t_type>(0))
450 return false;
451 }
452 else
453 {
454 if ((p[X] - vertex(C)[X]) * (vertex(B)[Y] - vertex(C)[Y]) - (vertex(B)[X] - vertex(C)[X]) * (p[Y] - vertex(C)[Y]) < cast<t_type>(0))
455 return false;
456 if ((p[X] - vertex(A)[X]) * (vertex(C)[Y] - vertex(A)[Y]) - (vertex(C)[X] - vertex(A)[X]) * (p[Y] - vertex(A)[Y]) < cast<t_type>(0))
457 return false;
458 }
459 return true;
460 }
461
462 /**--------------------------------------------------------------------------------------------------
463 Query if this object contains the given vertex.
464
465 Author: Tyler Parke
466
467 Date: 2017-11-17
468
469 Parameters:
470 vertex_point - The const t_vertex&amp; to test for containment.
471
472 \returns True if the object is in this collection, false if not.
473 **/
474
475 [[nodiscard]] constexpr bool contains(const t_vertex& vertex_point, t_type epsilon = t_type(0.0001)) const
476 {
477 //Check bounds first, as rest of code may take time
478 for(uint01 dim = 0; dim < t_dims; dim++)
479 if( getMax(vertex(A)[dim], vertex(B)[dim], vertex(C)[dim]) < vertex_point[dim]
480 || getMin(vertex(A)[dim], vertex(B)[dim], vertex(C)[dim]) > vertex_point[dim])
481 return false;
482 // Compute vectors
483 const t_vertex dca = vertex(C) - vertex(A);
484 const t_vertex dba = vertex(B) - vertex(A);
485 const t_vertex dbp = vertex_point - vertex(A);
486
487 // Compute dot products
488 t_type dotca = dot(dca, dca);
489 t_type dotcaba = dot(dca, dba);
490 t_type dotcabp = dot(dca, dbp);
491 t_type dotba = dot(dba, dba);
492 t_type dotbabp = dot(dba, dbp);
493
494 // Compute barycentric coordinates
495 t_type invDenom = (dotca * dotba - dotcaba * dotcaba);
496 t_type u = ((dotba * dotcabp) - (dotcaba * dotbabp)) / invDenom;
497 t_type v = ((dotca * dotbabp) - (dotcaba * dotcabp)) / invDenom;
498
499 // Check if point is in triangle
500 if ((u >= 0) && (v >= 0) && (u + v < 1))
501 {
502 return true;
503 }
504 else
505 {
506 for (uint01 location = edge_ab; location <= edge_ca; location++)
507 if (distanceSquared(edge(cast<TriangleLocation>(location)), vertex_point) <= epsilon)
508 return true;
509 }
510 return false;
511 }
512
513 /**--------------------------------------------------------------------------------------------------
514
515 Shares object.
516
517 Author: Tyler Parke
518
519 Date: 2017-11-17
520
521 Parameters:
522 object_to_check - The object to check.
523 tri - The triangle.
524 epsilon - (Optional) The epsilon.
525
526 \returns A TriangleLocation.
527 **/
528
529 [[nodiscard]] constexpr TriangleLocation sharesObject(TriangleLocation object_to_check, const Triangle<t_dims, t_type, t_vertex>& tri, t_type epsilon = 0) const
530 {
531 switch (object_to_check)
532 {
533 case edge_ab:
534 case edge_bc:
535 case edge_ca:
536 {
537 const LineSegment<t_dims, t_type> edge_a = edge(object_to_check);
538 for (uint01 i = edge_ab; i <= edge_ca; i++)
539 {
541 if (equals(edge_a, edge_b, epsilon))
542 return cast<TriangleLocation>(i);
543 }
544 return tri_location_nan;
545 }
546 case vertex_a:
547 case vertex_b:
548 case vertex_c:
549 {
550 const t_vertex vertex_1 = vertex(object_to_check);
551 for (uint01 i = vertex_a; i <= vertex_c; i++)
552 {
553 t_vertex vertex_2 = tri.vertex(cast<TriangleLocation>(i));
554 if (equals(vertex_1, vertex_2, epsilon))
555 return cast<TriangleLocation>(i);
556 }
557 return tri_location_nan;
558 }
559 case angle_a:
560 case angle_b:
561 case angle_c:
562 return tri_location_nan;
563 case inside_tri:
564 case outside_tri:
565 {
566 const t_vertex vertex_a = vertex(object_to_check);
567 for (uint01 i = 0; i <= 2; i++)
568 {
569 t_vertex vertex_b = tri.vertex(i);
570 if (equals(vertex_a, vertex_b, epsilon))
571 return cast<TriangleLocation>(i);
572 }
573 return tri_location_nan;
574 }
575 default:
576 return tri_location_nan;
577 }
578 }
579
580 /**--------------------------------------------------------------------------------------------------
581
582 Gets a location.
583
584 Author: Tyler Parke
585
586 Date: 2017-11-17
587
588 Parameters:
589 p - A Vector&lt;t_dims,t_type&gt; to process.
590 epsilon - (Optional) The epsilon.
591
592 \returns The location.
593 **/
594 [[nodiscard]] constexpr uint01 vertexIndex(const t_vertex& p) const
595 {
596 for (uint01 i = A; i <= C; ++i)
597 if (vertex(i) == p)
598 return i;
600 }
601 [[nodiscard]] constexpr TriangleLocation getIdentityOf(const t_vertex& p) const
602 {
603 for (uint01 i = A; i <= C; ++i)
604 if (vertex(i) == p)
606 return tri_location_nan;
607 }
608 [[nodiscard]] constexpr TriangleLocation getIdentityOf(const t_vertex& p, t_type epsilon) const
609 {
610 lib_assert(!IsInvalid(p), "Cannot get triangle identity of Invalid type");
611 for (uint01 i = A; i <= C; ++i)
612 if (equals(vertex(i), p, epsilon))
614 return tri_location_nan;
615 }
616 [[nodiscard]] constexpr TriangleLocation getIdentityOf(const LineSegment<t_dims, t_type, t_vertex>& line, t_type epsilon) const
617 {
618 switch (getIdentityOf(line[A], epsilon))
619 {
620 case vertex_a:
621 switch (getIdentityOf(line[B], epsilon))
622 {
623 case vertex_a: return vertex_a;
624 case vertex_b: return edge_ab;
625 case vertex_c: return edge_ca;
626 default: return tri_location_nan;
627 }
628 case vertex_b:
629 switch (getIdentityOf(line[B], epsilon))
630 {
631 case vertex_a: return edge_ab;
632 case vertex_b: return vertex_b;
633 case vertex_c: return edge_bc;
634 default: return tri_location_nan;
635 }
636 case vertex_c:
637 switch (getIdentityOf(line[B], epsilon))
638 {
639 case vertex_a: return edge_ca;
640 case vertex_b: return edge_bc;
641 case vertex_c: return vertex_c;
642 default: return tri_location_nan;
643 }
644 default: return tri_location_nan;
645 }
646 }
648 {
649 switch (getIdentityOf(line[A]))
650 {
651 case vertex_a:
652 switch (getIdentityOf(line[B]))
653 {
654 case vertex_a: return vertex_a;
655 case vertex_b: return edge_ab;
656 case vertex_c: return edge_ca;
657 default: return tri_location_nan;
658 }
659 case vertex_b:
660 switch (getIdentityOf(line[B]))
661 {
662 case vertex_a: return edge_ab;
663 case vertex_b: return vertex_b;
664 case vertex_c: return edge_bc;
665 default: return tri_location_nan;
666 }
667 case vertex_c:
668 switch (getIdentityOf(line[B]))
669 {
670 case vertex_a: return edge_ca;
671 case vertex_b: return edge_bc;
672 case vertex_c: return vertex_c;
673 default: return tri_location_nan;
674 }
675 default: return tri_location_nan;
676 }
677 }
678 [[nodiscard]] constexpr TriangleLocation getLocation(const t_vertex& p, t_type epsilon = cast<t_type>(0)) const
679 {
680 lib_assert(!IsInvalid(p), "Cannot get triangle location of Invalid type");
681 for (uint01 i = A; i <= C; ++i)
682 if (equals(vertex(i), p, epsilon))
683 return cast<TriangleLocation>(i);
684 for(uint01 location = edge_ab; location <= edge_ca; location++)
685 if(distanceSquared(edge(cast<TriangleLocation>(location)), p) <= epsilon)
686 return cast<TriangleLocation>(location);
687
688 const t_vertex normal_abp = Triangle(vertex(A), vertex(B), p).normal<true>();
689 const t_vertex normal_bcp = Triangle(vertex(B), vertex(C), p).normal<true>();
690
691 const t_type dot_1 = dot(normal_abp, normal_bcp);
692 if(dot_1 >= epsilon + 1 || dot_1 <= -epsilon + 1)
693 return outside_tri;
694
695 const t_vertex normal_cap = Triangle(vertex(C), vertex(A), p).normal<true>();
696 const t_type dot_2 = dot(normal_bcp, normal_cap);
697 if((dot_2 >= epsilon + 1 && dot_2 <= -epsilon + 1))
698 return outside_tri;
699 return inside_tri;
700 }
701
702 [[nodiscard]] constexpr TriangleLocation getLocation(const LineSegment<t_dims, t_type, t_vertex>& line, t_type epsilon = cast<t_type>(0)) const
703 {
704 switch (getLocation(line[A], epsilon))
705 {
706 case edge_ab:
707 switch (getLocation(line[B], epsilon))
708 {
709 case vertex_a:
710 case vertex_b:
711 case edge_ab: return edge_ab;
712 case vertex_c:
713 case edge_ca:
714 case edge_bc:
715 case inside_tri: return inside_tri;
716 default: return mixed_location_tri;
717 }
718 case edge_bc:
719 switch (getLocation(line[B], epsilon))
720 {
721 case vertex_b:
722 case vertex_c:
723 case edge_bc: return edge_bc;
724 case vertex_a:
725 case edge_ca:
726 case edge_ab:
727 case inside_tri: return inside_tri;
728 default: return mixed_location_tri;
729 }
730 case edge_ca:
731 switch (getLocation(line[B], epsilon))
732 {
733 case vertex_c:
734 case vertex_a:
735 case edge_ca: return edge_ca;
736 case vertex_b:
737 case edge_ab:
738 case edge_bc:
739 case inside_tri: return inside_tri;
740 default: return mixed_location_tri;
741 }
742 case vertex_a:
743 switch (getLocation(line[B], epsilon))
744 {
745 case vertex_c: return edge_ca;
746 case vertex_b: return edge_ab;
747 case vertex_a: return vertex_a;
748 case edge_ca: return edge_ca;
749 case edge_ab: return edge_ab;
750 case edge_bc:
751 case inside_tri: return inside_tri;
752 default: return mixed_location_tri;
753 }
754 case vertex_b:
755 switch (getLocation(line[B], epsilon))
756 {
757 case vertex_b: return vertex_b;
758 case vertex_c: return edge_bc;
759 case vertex_a: return edge_ab;
760 case edge_bc: return edge_bc;
761 case edge_ab: return edge_ab;
762 case edge_ca:
763 case inside_tri: return inside_tri;
764 default: return mixed_location_tri;
765 }
766 case vertex_c:
767 switch (getLocation(line[B], epsilon))
768 {
769 case vertex_c: return vertex_c;
770 case vertex_b: return edge_bc;
771 case vertex_a: return edge_ca;
772 case edge_bc: return edge_bc;
773 case edge_ca: return edge_ca;
774 case edge_ab:
775 case inside_tri: return inside_tri;
776 default: return mixed_location_tri;
777 }
778 case inside_tri:
779 if (getLocation(line[B], epsilon) == outside_tri)
780 return mixed_location_tri;
781 else
782 return inside_tri;
783 case outside_tri:
784 if (getLocation(line[B], epsilon) == outside_tri)
785 return outside_tri;
786 else
787 return mixed_location_tri;
788 default:
789 lib_assert(false, "Should never arrive here in triangle identity line");
790 }
791 lib_assert(false, "Should never arrive here in triangle identity line");
792 return tri_location_nan;
793 }
794
795 /**--------------------------------------------------------------------------------------------------
796 Inverts this object.
797
798 Author: Tyler Parke
799
800 Date: 2017-11-17
801 **/
802
803 constexpr void invert()
804 {
805 std::swap(vertex(C), vertex(B));
806 }
807
808
809
810 /**--------------------------------------------------------------------------------------------------
811 Returns the point counter-clockwise to given point. Note the given point must be a vertex of the triangle
812
813 Author: Tyler Parke
814
815 Date: 2017-05-15
816 **/
817 constexpr const t_vertex& nextVertexCCW(const t_vertex& point) const
818 {
819 return vertex(NextVertexCCW(getIdentityOf(point)));
820 }
821
822 /**--------------------------------------------------------------------------------------------------
823 Returns the point clockwise to given point. Note the given point must be a vertex of the triangle
824
825 Author: Tyler Parke
826
827 Date: 2017-05-15
828 **/
829 constexpr const t_vertex& nextVertexCW(const t_vertex& point) const
830 {
831 return vertex(NextVertexCW(getIdentityOf(point)));
832 }
833 bool hasVertex(const t_vertex& point) const
834 {
835 return point == vertex(A) || point == vertex(B) || point == vertex(C);
836 }
837 };
838
839
840
841
842 /**--------------------------------------------------------------------------------------------------
843
844 Closest point.
845
846 Author: Tyler Parke
847
848 Date: 2017-11-17
849
850 Parameters:
851 tri - The triangle.
852 point - The point.
853
854 \returns A Vector&lt;t_dims,t_type&gt;
855 **/
856 template<uint01 t_dims, class t_type, class t_vertex>
857 constexpr Vector<t_dims, t_type> ClosestPoint(const Triangle<t_dims, t_type, t_vertex>& tri, const t_vertex& point)
858 {
859 const t_vertex edge0 = tri.edge(B, A).ray();
860 const t_vertex edge1 = tri.edge(C, A).ray();
861
862 const t_type a = dot(edge0, edge0);
863 const t_type b = dot(edge0, edge1);
864 const t_type c = dot(edge1, edge1);
865
866 const t_type det = a * c - b * b;
867
868 return ClosestPoint(tri, point, edge0, edge1, a, b, c, det);
869 }
870
871 template<uint01 t_dims, class t_type, class t_vertex>
872 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)
873 {
874 const t_vertex v0(tri.vertex(A) - point);
875 const t_type d = dot(edge0, v0);
876 const t_type e = dot(edge1, v0);
877
878 t_type s = b * e - c * d;
879 t_type t = b * d - a * e;
880
881 if (s + t < det)
882 {
883 if (s < cast<t_type>(0))
884 {
885 if (t < cast<t_type>(0))
886 {
887 if (d < cast<t_type>(0))
888 {
889 s = clip(-d / a, cast<t_type>(0), cast<t_type>(1));
890 t = cast<t_type>(0);
891 }
892 else
893 {
894 s = cast<t_type>(0);
895 t = clip(-e / c, cast<t_type>(0), cast<t_type>(1));
896 }
897 }
898 else
899 {
900 s = cast<t_type>(0);
901 t = clip(-e / c, cast<t_type>(0), cast<t_type>(1));
902 }
903 }
904 else if (t < cast<t_type>(0))
905 {
906 s = clip(-d / a, cast<t_type>(0), cast<t_type>(1));
907 t = cast<t_type>(0);
908 }
909 else
910 {
911 t_type invDet = cast<t_type>(1) / det;
912 s *= invDet;
913 t *= invDet;
914 }
915 }
916 else
917 {
918 if (s < cast<t_type>(0))
919 {
920 t_type tmp0 = b + d;
921 t_type tmp1 = c + e;
922 if (tmp1 > tmp0)
923 {
924 t_type numer = tmp1 - tmp0;
925 t_type denom = a - 2 * b + c;
926 s = clip(numer / denom, cast<t_type>(0), cast<t_type>(1));
927 t = 1 - s;
928 }
929 else
930 {
931 t = clip(-e / c, 0.f, 1.f);
932 s = cast<t_type>(0);
933 }
934 }
935 else if (t < cast<t_type>(0))
936 {
937 if (a + d > b + e)
938 {
939 t_type numer = c + e - b - d;
940 t_type denom = a - 2 * b + c;
941 s = clip(numer / denom, cast<t_type>(0), cast<t_type>(1));
942 t = 1 - s;
943 }
944 else
945 {
946 s = clip(-e / c, cast<t_type>(0), cast<t_type>(1));
947 t = cast<t_type>(0);
948 }
949 }
950 else
951 {
952 t_type numer = c + e - b - d;
953 t_type denom = a - 2 * b + c;
954 s = clip(numer / denom, cast<t_type>(0), cast<t_type>(1));
955 t = cast<t_type>(1) - s;
956 }
957 }
958
959 return tri.vertex(A) + s * edge0 + t * edge1;
960 }
961
962 /**--------------------------------------------------------------------------------------------------
963
964 Tests if objects are considered equal.
965
966 Author: Tyler Parke
967
968 Date: 2017-11-17
969
970 Parameters:
971 tri_a - Constant triangle&lt;t dims,t type,t vertex&gt;&amp; to be compared.
972 tri_b - Constant triangle&lt;t dims,t type,t vertex&gt;&amp; to be compared.
973 epsilon - (Optional) T type to be compared.
974
975 \returns True if the objects are considered equal, false if they are not.
976 **/
977 template<bool t_has_winding, uint01 t_dims, class t_type, class t_vertex>
978 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)
979 {
980 uint01 dif = 0;
981 for (uint01 n = A; n <= C; ++n)
982 {
983 if(equals(tri_a.vertex(A), tri_b.vertex(n), epsilon))
984 break;
985 dif++;
986 }
987 if (tri_a.vertex(B) == tri_b.vertex((B + dif) % 3))
988 {
989 if (tri_a.vertex(C) == tri_b.vertex((C + dif) % 3))
990 return true;
991 }
992 else if(!t_has_winding && tri_a.vertex(B) == tri_b.vertex((C + dif) % 3))
993 {
994 if (tri_a.vertex(C) == tri_b.vertex((A + dif) % 3))
995 return true;
996 }
997 return false;
998 }
999
1000
1001
1002
1003 template<uint01 t_dims, class t_type, class t_vector>
1004 struct Constant<Triangle<t_dims, t_type, t_vector>>
1005 {
1006 constexpr const static Triangle<t_dims, t_type, t_vector> Invalid{ Constant<t_vector>::Invalid, Constant<t_vector>::Invalid, Constant<t_vector>::Invalid };
1007 constexpr const static Triangle<t_dims, t_type, t_vector> Min{ Constant<t_vector>::Min, Constant<t_vector>::Min, Constant<t_vector>::Min };
1008 constexpr const static Triangle<t_dims, t_type, t_vector> Max{ Constant<t_vector>::Max, Constant<t_vector>::Max, Constant<t_vector>::Max };
1009 };
1010
1011 template<uint01 t_dims, class t_type>
1012 static constexpr bool IsInvalid(const Triangle<t_dims, t_type>& value)
1013 {
1014 for (uint01 dim = 0; dim < t_dims; ++dim)
1015 {
1016 if (IsInvalid(value[dim]))
1017 return true;
1018 }
1019 return false;
1020 }
1021};
#define lib_assert(expression, message)
Definition LibAssert.h:61
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)
Definition AngleFunctions.h:694
The primary angle storage class for this API. Stores an angle in an optimized format.
Definition StringStream.h:540
A line segment represented by two vertices, a start and end.
Definition Line.hpp:49
Base class for N-dimensional triangles.
Definition Triangle.hpp:66
static constexpr TriangleLocation NextVertexCCW(TriangleLocation location)
Returns the point location counter-clockwise to given point location.
Definition Triangle.hpp:92
static constexpr TriangleLocation oppositeLocation(TriangleLocation location)
Definition Triangle.hpp:68
static constexpr TriangleLocation NextVertexCW(TriangleLocation location)
Returns the point location clockwise to given point location.
Definition Triangle.hpp:112
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 Vector< t_dims, t_normal_type > normal() const
Definition Triangle.hpp:421
constexpr Triangle< t_new_dims, t_new_type > as() const
Definition Triangle.hpp:405
constexpr bool contains(const Vector< t_dims - 1, t_type > &p) const
Definition Triangle.hpp:443
constexpr t_vertex & vertex(uint01 triangle_node)
Definition Triangle.hpp:216
constexpr t_vertex centroid() const
Definition Triangle.hpp:372
constexpr LineSegment< t_dims, t_type, t_vertex > edge(TriangleLocation location) const
Edges the given location.
Definition Triangle.hpp:275
constexpr uint01 vertexIndex(const t_vertex &p) const
Definition Triangle.hpp:594
constexpr const t_vertex & vertex(TriangleLocation triangle_node) const
Vertices the given triangle node.
Definition Triangle.hpp:192
constexpr TriangleLocation getLocation(const LineSegment< t_dims, t_type, t_vertex > &line, t_type epsilon=cast< t_type >(0)) const
Definition Triangle.hpp:702
constexpr t_area_type area() const
Definition Triangle.hpp:357
constexpr Triangle(const t_vertex &vector)
Definition Triangle.hpp:148
constexpr TriangleLocation getIdentityOf(const LineSegment< t_dims, t_type, t_vertex > &line) const
Definition Triangle.hpp:647
constexpr TriangleLocation getLocation(const t_vertex &p, t_type epsilon=cast< t_type >(0)) const
Definition Triangle.hpp:678
constexpr const t_vertex & vertex(uint01 triangle_node) const
Definition Triangle.hpp:235
constexpr TriangleLocation sharesObject(TriangleLocation object_to_check, const Triangle< t_dims, t_type, t_vertex > &tri, t_type epsilon=0) const
Definition Triangle.hpp:529
constexpr Triangle(const t_type &a)
Definition Triangle.hpp:142
constexpr TriangleLocation getIdentityOf(const LineSegment< t_dims, t_type, t_vertex > &line, t_type epsilon) const
Definition Triangle.hpp:616
constexpr Triangle(const t_vertex &a, const t_vertex &b, const t_vertex &c)
Definition Triangle.hpp:151
constexpr fltp08 tan(uint01 triangle_node) const
Definition Triangle.hpp:307
bool hasVertex(const t_vertex &point) const
Definition Triangle.hpp:833
constexpr bool contains(const t_vertex &vertex_point, t_type epsilon=t_type(0.0001)) const
Definition Triangle.hpp:475
constexpr void invert()
Definition Triangle.hpp:803
constexpr Triangle()
Definition Triangle.hpp:140
constexpr Triangle(const t_type &a, const t_type &b, const t_type &c)
Definition Triangle.hpp:145
constexpr t_vertex center() const
Definition Triangle.hpp:387
constexpr const t_vertex & nextVertexCCW(const t_vertex &point) const
Definition Triangle.hpp:817
constexpr TriangleLocation getIdentityOf(const t_vertex &p, t_type epsilon) const
Definition Triangle.hpp:608
constexpr t_vertex & vertex(TriangleLocation triangle_node)
Vertices the given triangle node.
Definition Triangle.hpp:168
constexpr Angle< t_angle_type > angle(TriangleLocation location) const
Definition Triangle.hpp:335
constexpr LineSegment< t_dims, t_type, t_vertex > edge(uint01 triangle_node_a, uint01 triangle_node_b) const
Definition Triangle.hpp:256
constexpr TriangleLocation getIdentityOf(const t_vertex &p) const
Definition Triangle.hpp:601
constexpr const t_vertex & nextVertexCW(const t_vertex &point) const
Definition Triangle.hpp:829
constexpr Angle< t_angle_type > angle(uint01 triangle_node) const
Definition Triangle.hpp:299
A fixed-size array with better performance compared to dynamic containers.
Definition Vector.hpp:60
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:464
constexpr t_type magnitudeSquared() const
Definition Vector.hpp:426
Definition ACIColor.h:37
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
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.
Definition BaseFunctions.hpp:207
t_type dot(const Vector< t_dims, t_type > &v1, const Vector< t_dims, t_type > &v2)
Definition VectorFunctions.hpp:1030
TriangleLocation
Values that represent triangle locations.
Definition Triangle.hpp:47
@ angle_c
Definition Triangle.hpp:57
@ edge_ab
Definition Triangle.hpp:49
@ mixed_location_tri
Definition Triangle.hpp:59
@ angle_b
Definition Triangle.hpp:56
@ vertex_a
Definition Triangle.hpp:52
@ inside_tri
Definition Triangle.hpp:58
@ angle_a
Definition Triangle.hpp:55
@ tri_location_nan
Definition Triangle.hpp:60
@ edge_bc
Definition Triangle.hpp:50
@ edge_ca
Definition Triangle.hpp:51
@ vertex_b
Definition Triangle.hpp:53
@ outside_tri
Definition Triangle.hpp:48
@ vertex_c
Definition Triangle.hpp:54
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:80
@ RADIANS
Definition Angle.h:57
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)
Definition Triangle.hpp:978
t_type distanceSquared(const Bounds< t_dims, t_type, t_vertex > &bounds, const Vector< t_dims, t_type > &vertex)
Definition Distance.hpp:46
constexpr Vector< 1, t_type > cross(const Vector< 1, t_type > &, const Vector< 1, t_type > &)
Definition VectorFunctions.hpp:898
t_type sqrt(const t_type &value)
Definition VectorFunctions.hpp:1225
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:375
constexpr Vector< t_dims, t_type > ClosestPoint(const Triangle< t_dims, t_type, t_vertex > &tri, const t_vertex &point)
Definition Triangle.hpp:857
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))
Definition Line.hpp:757
@ 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
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
Defines for a given type (such as sint04, fltp08, UUID, etc) a maximum, minimum, and reserved 'invali...
Definition BaseValues.hpp:233
static const t_type Invalid
Definition BaseValues.hpp:234
static const t_type Min
Definition BaseValues.hpp:235
static const t_type Max
Definition BaseValues.hpp:236