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