Ocean
Loading...
Searching...
No Matches
Triangle2.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_MATH_TRIANGLE_2_H
9#define META_OCEAN_MATH_TRIANGLE_2_H
10
11#include "ocean/math/Math.h"
13#include "ocean/math/Triangle.h"
14#include "ocean/math/Vector2.h"
15#include "ocean/math/Vector3.h"
16
17namespace Ocean
18{
19
20// Forward declaration.
21template <typename T> class TriangleT2;
22
23/**
24 * Definition of the Triangle2 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single or double precision float data type.
25 * @see TriangleT2
26 * @ingroup math
27 */
29
30/**
31 * Instantiation of the TriangleT2 template class using a double precision float data type.
32 * @see TriangleT2
33 * @ingroup math
34 */
36
37/**
38 * Instantiation of the TriangleT2 template class using a single precision float data type.
39 * @see TriangleT2
40 * @ingroup math
41 */
43
44/**
45 * Definition of a typename alias for vectors with TriangleT2 objects.
46 * @see TriangleT2
47 * @ingroup math
48 */
49template <typename T>
50using TrianglesT2 = std::vector<TriangleT2<T>>;
51
52/**
53 * Definition of a vector holding 2D triangles.
54 * @see Triangle2
55 * @ingroup math
56 */
57using Triangles2 = std::vector<Triangle2>;
58
59/**
60 * Definition of a vector holding 2D triangles with single precision float data type.
61 * @see Triangle2
62 * @ingroup math
63 */
64using TrianglesF2 = std::vector<TriangleF2>;
65
66/**
67 * Definition of a vector holding 2D triangles with double precision float data type.
68 * @see Triangle2
69 * @ingroup math
70 */
71using TrianglesD2 = std::vector<TriangleD2>;
72
73/**
74 * This class implements a 2D triangle with Cartesian coordinates.
75 * @tparam T Data type used to represent coordinates
76 * @see TriangleF2, TriangleD2, TriangleT3.
77 * @ingroup math
78 */
79template <typename T>
80class TriangleT2 : public TriangleT<T>
81{
82 public:
83
84 /**
85 * Creates a new 2D triangle object with default parameters.
86 */
87 TriangleT2() = default;
88
89 /**
90 * Creates a new 2D triangle object by three corner positions.
91 * @param point0 First corner position
92 * @param point1 Second corner position
93 * @param point2 Third corner position
94 */
95 inline TriangleT2(const VectorT2<T>& point0, const VectorT2<T>& point1, const VectorT2<T>& point2);
96
97 /**
98 * Returns the first triangle corner.
99 * @return First triangle corner
100 */
101 inline const VectorT2<T>& point0() const;
102
103 /**
104 * Returns the second triangle corner.
105 * @return Second triangle corner
106 */
107 inline const VectorT2<T>& point1() const;
108
109 /**
110 * Returns the third triangle corner.
111 * @return Third triangle corner
112 */
113 inline const VectorT2<T>& point2() const;
114
115 /**
116 * Returns the square distance between point0 and point1.
117 * @return Square distance
118 */
119 inline T sqrDistance01() const;
120
121 /**
122 * Returns the square distance between point0 and point2.
123 * @return Square distance
124 */
125 inline T sqrDistance02() const;
126
127 /**
128 * Returns the square distance between point1 and point2.
129 * @return Square distance
130 */
131 inline T sqrDistance12() const;
132
133 /**
134 * Returns the most left position of this triangle.
135 * @return Left position
136 */
137 inline T left() const;
138
139 /**
140 * Returns the most top position of this triangle.
141 * @return Top position
142 */
143 inline T top() const;
144
145 /**
146 * Returns the most right position of this triangle.
147 * @return Right position
148 */
149 inline T right() const;
150
151 /**
152 * Returns the most bottom position of this triangle.
153 * @return Bottom position
154 */
155 inline T bottom() const;
156
157 /**
158 * Returns the area of this triangle.
159 * @return Triangle area
160 * @see area2().
161 */
162 inline T area() const;
163
164 /**
165 * Returns the square area of this triangle.
166 * The result is clamped to zero, as the expanded Heron form can cancel to a small negative value for near-collinear triangles.
167 * @return Triangle area, with range [0, infinity)
168 * @see area().
169 */
170 inline T area2() const;
171
172 /**
173 * Calculates the three angle cosine values of the three triangle corners.
174 * Beware: Make sure that this triangle is valid before!
175 * @param cosine0 Resulting angle corresponding to point0
176 * @param cosine1 Resulting angle corresponding to point1
177 * @param cosine2 Resulting angle corresponding to point2
178 */
179 void cosines(T& cosine0, T& cosine1, T& cosine2) const;
180
181 /**
182 * Calculates the three angles of the three triangle corners.
183 * Beware: Make sure that this triangle is valid before!
184 * @param angle0 Resulting angle corresponding to point0 in radian
185 * @param angle1 Resulting angle corresponding to point1 in radian
186 * @param angle2 Resulting angle corresponding to point2 in radian
187 */
188 inline void angles(T& angle0, T& angle1, T& angle2) const;
189
190 /**
191 * Returns the minimal angle of this triangle.
192 * Beware: Make sure that this triangle is valid before!
193 * @return Minimal angle in radian
194 */
195 inline T minAngle() const;
196
197 /**
198 * Returns whether all cosine values of the three triangle corners are below or equal to a given threshold.
199 * Thus, to test whether the minimal corner angle is equal to PI/8, then allCosineBelow(cos(PI/8)) has to be checked.
200 * @param cosValue Cosine threshold value
201 * @return True, if so
202 */
203 bool allCosineBelow(const T cosValue) const;
204
205 /**
206 * Returns the maximal square side length of this triangle.
207 * @return Maximal square side length
208 */
209 inline T maxSqrLength() const;
210
211 /**
212 * Returns the maximal side length of this triangle.
213 * @return Maximal side length
214 */
215 inline T maxLength() const;
216
217 /**
218 * Returns the minimal square side length of this triangle.
219 * @return Minimal square side length
220 */
221 inline T minSqrLength() const;
222
223 /**
224 * Returns the minimal side length of this triangle.
225 * @return Minimal side length
226 */
227 inline T minLength() const;
228
229 /**
230 * Returns whether a given point lies inside this triangle.
231 * @param point The point to be checked
232 * @return True, if so
233 */
234 inline bool isInside(const VectorT2<T>& point) const;
235
236 /**
237 * Returns whether a given point lies inside at least one of the given triangles.
238 * @param triangles The triangles that are tested
239 * @param point The point to be checked
240 * @return True, if so
241 */
242 static inline bool isInside(const std::vector<TriangleT2<T>>& triangles, const VectorT2<T>& point);
243
244 /**
245 * Returns whether this triangles is defined in a counter clockwise manner.
246 * The result of the function depends on the coordinate system in which the points are defined:
247 * <pre>
248 * First coordinate system, Second coordinate system
249 *
250 * ------> x-axis ^
251 * | | y-axis
252 * | |
253 * | y-axis |
254 * V ------> x-axis
255 *
256 * </pre>
257 * @param yAxisDownwards True, if the y-axis points downwards and x-axis points to the right; False, if the y-axis points upwards and the x-axis points to the right
258 * @return True, if so
259 */
260 inline bool isCounterClockwise(const bool yAxisDownwards = true) const;
261
262 /**
263 * Returns the 2D Cartesian coordinate of a given barycentric coordinate defined in relation to this triangle.
264 * @param barycentric The Barycentric coordinate to convert to a Cartesian coordinate
265 * @return Cartesian coordinate
266 */
267 inline VectorT2<T> barycentric2cartesian(const VectorT3<T>& barycentric) const;
268
269 /**
270 * Returns the barycentric coordinate of a given 2D Cartesian coordinate defined in relation to this triangle.
271 * @param cartesian The Cartesian coordinate to convert to a barycentric coordinate
272 * @return Barycentric coordinate
273 */
274 inline VectorT3<T> cartesian2barycentric(const VectorT2<T>& cartesian) const;
275
276 /**
277 * Returns the circumcenter for this triangle in barycentric coordinates.
278 * @return Barycentric coordinates of the circumcenter
279 */
281
282 /**
283 * Returns the circumcenter for this triangle in Cartesian coordinates.
284 * @return Cartesian coordinates of the circumcenter
285 */
286 inline VectorT2<T> cartesianCircumcenter() const;
287
288 /**
289 * Returns the incenter for this triangle in barycentric coordinates.
290 * @return Barycentric coordinates of the incenter
291 */
293
294 /**
295 * Returns the incenter for this triangle in Cartesian coordinates.
296 * @return Cartesian coordinates of the circumcenter
297 */
298 inline VectorT2<T> cartesianIncenter() const;
299
300 /**
301 * Returns whether this triangle has an intersection with a second triangle.
302 * @param triangle The second triangle to test
303 * @return True, if so
304 */
305 bool intersects(const TriangleT2<T>& triangle) const;
306
307 /**
308 * Pad a given 2D triangle along each edge by a fixed value. For a positive pad width, each side of the resulting triangle is shifted away from the triangle circumcenter along the perpendicular.
309 * @param padWidth Absolute amount to shift the triangle edges out from the triangle circumcenter, with range (-infinity, infinity); note that, in the case where the padding is negative with an absolute value smaller than the shortest distance from the circumcenter to an edge, then the triangle will flip its orientation
310 * @return Padded 2D triangle
311 */
312 TriangleT2<T> padded(const T padWidth) const;
313
314 /**
315 * Returns whether this triangle can provide valid barycentric coordinates (for 64 bit floating point values).
316 * For 32 bit floating point values we simply check whether all three corners of the triangle are different.
317 * @return True, if so
318 */
319 inline bool isValid() const;
320
321 /**
322 * Returns individual triangle corners.
323 * @param index Index of the corner that is requested, with range [0, 2]
324 * @return Resulting triangle corner
325 */
326 inline const VectorT2<T>& operator[](const unsigned int index) const;
327
328 /**
329 * Shifts the triangle by a given 2D vector (by adding the vector to all three corners of the triangle).
330 * @param offset The offset vector to shift the triangle
331 * @return The new shifted triangle
332 */
333 inline TriangleT2<T> operator+(const VectorT2<T>& offset) const;
334
335 /**
336 * Shifts the triangle by a given 2D vector (by adding the vector to all three corners of the triangle).
337 * @param offset The offset vector to shift the triangle
338 * @return The reference to this triangle
339 */
340 inline TriangleT2<T>& operator+=(const VectorT2<T>& offset);
341
342 /**
343 * Shifts the triangle by a given 2D vector (by subtracting the vector from all three corners of the triangle).
344 * @param offset The offset vector to shift the triangle
345 * @return The new shifted triangle
346 */
347 inline TriangleT2<T> operator-(const VectorT2<T>& offset) const;
348
349 /**
350 * Shifts the triangle by a given 2D vector (by subtracting the vector from all three corners of the triangle).
351 * @param offset The offset vector to shift the triangle
352 * @return The reference to this triangle
353 */
354 inline TriangleT2<T>& operator-=(const VectorT2<T>& offset);
355
356 /**
357 * Analyses the layout of three 2D points forming either a triangle or a line.
358 * The result of the function depends on the coordinate system in which the points are defined:
359 * <pre>
360 * First coordinate system, Second coordinate system
361 *
362 * ------> x-axis ^
363 * | | y-axis
364 * | |
365 * | y-axis |
366 * V ------> x-axis
367 *
368 * </pre>
369 * @param point0 The first point to be analyzed
370 * @param point1 The first point to be analyzed
371 * @param point2 The first point to be analyzed
372 * @param yAxisDownwards True, if the y-axis points downwards and x-axis points to the right; False, if the y-axis points upwards and the x-axis points to the right
373 * @return A negative value if the three points define a counter clockwise triangle, a positive value for a clockwise triangle, zero is the tree points are located on a line, with range (-infinity, infinity)
374 */
375 static T analyzePoints(const VectorT2<T>& point0, const VectorT2<T>& point1, const VectorT2<T>& point2, const bool yAxisDownwards);
376
377 private:
378
379 /// The corner positions.
380 VectorT2<T> points_[3] = {VectorT2<T>(T(0), T(0)), VectorT2<T>(T(0), T(0)), VectorT2<T>(T(0), T(0))};
381
382 /// Convert factor for barycentric coordinates.
384};
385
386template <typename T>
387inline TriangleT2<T>::TriangleT2(const VectorT2<T>& point0, const VectorT2<T>& point1, const VectorT2<T>& point2) :
388 barycentricFactor_(T(0))
389{
390 points_[0] = point0;
391 points_[1] = point1;
392 points_[2] = point2;
393
394 const T factor = (points_[1].y() - points_[2].y()) * (points_[0].x() - points_[2].x())
395 + (points_[2].x() - points_[1].x()) * (points_[0].y() - points_[2].y());
396
397 if (NumericT<T>::isNotEqualEps(factor))
398 {
399 barycentricFactor_ = T(1) / factor;
400 }
401}
402
403template <typename T>
405{
406 return points_[0];
407}
408
409template <typename T>
411{
412 return points_[1];
413}
414
415template <typename T>
417{
418 return points_[2];
419}
420
421template <typename T>
423{
424 return points_[0].sqrDistance(points_[1]);
425}
426
427template <typename T>
429{
430 return points_[0].sqrDistance(points_[2]);
431}
432
433template <typename T>
435{
436 return points_[1].sqrDistance(points_[2]);
437}
438
439template <typename T>
440inline T TriangleT2<T>::left() const
441{
442 ocean_assert(isValid());
443 return min(points_[0].x(), min(points_[1].x(), points_[2].x()));
444}
445
446template <typename T>
447inline T TriangleT2<T>::top() const
448{
449 ocean_assert(isValid());
450 return min(points_[0].y(), min(points_[1].y(), points_[2].y()));
451}
452
453template <typename T>
454inline T TriangleT2<T>::right() const
455{
456 ocean_assert(isValid());
457 return max(points_[0].x(), max(points_[1].x(), points_[2].x()));
458}
459
460template <typename T>
461inline T TriangleT2<T>::bottom() const
462{
463 ocean_assert(isValid());
464 return max(points_[0].y(), max(points_[1].y(), points_[2].y()));
465}
466
467template <typename T>
468inline T TriangleT2<T>::area() const
469{
470 return NumericT<T>::sqrt(area2());
471}
472
473template <typename T>
474inline T TriangleT2<T>::area2() const
475{
476 const T a2 = points_[0].sqrDistance(points_[1]);
477 const T b2 = points_[0].sqrDistance(points_[2]);
478 const T c2 = points_[1].sqrDistance(points_[2]);
479
480 // the argument order keeps a NaN (from NaN coordinates) propagating into the sqrt() assert in area(), instead of silently clamping it to zero
481 return std::max((T(4) * a2 * c2 - NumericT<T>::sqr(a2 + c2 - b2)) * T(0.0625), T(0));
482}
483
484template <typename T>
485void TriangleT2<T>::cosines(T& cosine0, T& cosine1, T& cosine2) const
486{
487 ocean_assert(isValid());
488
489 const T sqrDistance01(points_[1].sqrDistance(points_[0]));
490 const T sqrDistance02(points_[2].sqrDistance(points_[0]));
491 const T sqrDistance12(points_[2].sqrDistance(points_[1]));
492
493 const T factorDistance01(T(1) / NumericT<T>::sqrt(sqrDistance01));
494 const T factorDistance02(T(1) / NumericT<T>::sqrt(sqrDistance02));
495 const T factorDistance12(T(1) / NumericT<T>::sqrt(sqrDistance12));
496
497 // c^2 = a^2 + b^2 - 2abcos
498 // cos = (a^2 + b^2 - c^2) / (2ab)
499
500 cosine0 = (sqrDistance01 + sqrDistance02 - sqrDistance12) * T(0.5) * factorDistance01 * factorDistance02;
501 cosine1 = (sqrDistance01 + sqrDistance12 - sqrDistance02) * T(0.5) * factorDistance01 * factorDistance12;
502 cosine2 = (sqrDistance02 + sqrDistance12 - sqrDistance01) * T(0.5) * factorDistance02 * factorDistance12;
503
505}
506
507template <typename T>
508bool TriangleT2<T>::allCosineBelow(const T cosValue) const
509{
510 ocean_assert(isValid());
511
512 const T sqrDistance01(points_[1].sqrDistance(points_[0]));
513 const T sqrDistance02(points_[2].sqrDistance(points_[0]));
514 const T sqrDistance12(points_[2].sqrDistance(points_[1]));
515
516 const T factorDistance01(T(1) / NumericT<T>::sqrt(sqrDistance01));
517 const T factorDistance02(T(1) / NumericT<T>::sqrt(sqrDistance02));
518 const T factorDistance12(T(1) / NumericT<T>::sqrt(sqrDistance12));
519
520 // c^2 = a^2 + b^2 - 2abcos
521 // cos = (a^2 + b^2 - c^2) / (2ab)
522
523 return (sqrDistance01 + sqrDistance02 - sqrDistance12) * T(0.5) * factorDistance01 * factorDistance02 <= cosValue
524 && (sqrDistance01 + sqrDistance12 - sqrDistance02) * T(0.5) * factorDistance01 * factorDistance12 <= cosValue
525 && (sqrDistance02 + sqrDistance12 - sqrDistance01) * T(0.5) * factorDistance02 * factorDistance12 <= cosValue;
526}
527
528template <typename T>
530{
531 ocean_assert(isValid());
532
533 const T a2 = points_[1].sqrDistance(points_[2]);
534 const T b2 = points_[0].sqrDistance(points_[2]);
535 const T c2 = points_[0].sqrDistance(points_[1]);
536
537 const T coord0 = a2 * (-a2 + b2 + c2);
538 const T coord1 = b2 * (a2 - b2 + c2);
539 const T coord2 = c2 * (a2 + b2 - c2);
540
541 const T total = coord0 + coord1 + coord2;
542 ocean_assert(NumericT<T>::isNotEqualEps(total));
543
544 const T factor = T(1) / total;
545
546 return VectorT3<T>(coord0 * factor, coord1 * factor, coord2 * factor);
547}
548
549template <typename T>
551{
552 ocean_assert(isValid());
553
554 const T a = points_[1].distance(points_[2]);
555 const T b = points_[0].distance(points_[2]);
556 const T c = points_[0].distance(points_[1]);
557
558 const T total = a + b + c;
559 ocean_assert(NumericT<T>::isNotEqualEps(total));
560
561 const T factor = T(1) / total;
562
563 return VectorT3<T>(a * factor, b * factor, c * factor);
564}
565
566template <typename T>
567bool TriangleT2<T>::intersects(const TriangleT2<T>& triangle) const
568{
569 ocean_assert(isValid() && triangle.isValid());
570
571 // check whether bounding boxes do not intersect
572 if (left() > triangle.right() || triangle.left() > right() || top() > triangle.bottom() || triangle.top() > bottom())
573 {
574 return false;
575 }
576
577 if (isInside(triangle.point0()) || isInside(triangle.point1()) || isInside(triangle.point2()) || triangle.isInside(point0()) || triangle.isInside(point1()) || triangle.isInside(point2()))
578 {
579 return true;
580 }
581
582 const FiniteLineT2<T> thisLines[3] =
583 {
584 FiniteLineT2<T>(point0(), point1()),
585 FiniteLineT2<T>(point1(), point2()),
586 FiniteLineT2<T>(point2(), point0())
587 };
588
589 const FiniteLineT2<T> triangleLines[3] =
590 {
591 FiniteLineT2<T>(triangle.point0(), triangle.point1()),
592 FiniteLineT2<T>(triangle.point1(), triangle.point2()),
593 FiniteLineT2<T>(triangle.point2(), triangle.point0())
594 };
595
596 return thisLines[0].intersects(triangleLines[0]) || thisLines[0].intersects(triangleLines[1]) || thisLines[0].intersects(triangleLines[2])
597 || thisLines[1].intersects(triangleLines[0]) || thisLines[1].intersects(triangleLines[1]) || thisLines[1].intersects(triangleLines[2])
598 || thisLines[2].intersects(triangleLines[0]) || thisLines[2].intersects(triangleLines[1]) || thisLines[2].intersects(triangleLines[2]);
599}
600
601template <typename T>
603{
604 ocean_assert(isValid());
605 ocean_assert(NumericT<T>::isNotEqualEps(padWidth));
606
607 if (!isValid())
608 {
609 return TriangleT2<T>();
610 }
611
612 if (NumericT<T>::isEqualEps(padWidth))
613 {
614 return *this;
615 }
616
617 // Create homogeneous 2D points.
618 const VectorT3<T> hPoint0(points_[0], T(1.0));
619 const VectorT3<T> hPoint1(points_[1], T(1.0));
620 const VectorT3<T> hPoint2(points_[2], T(1.0));
621
622 VectorT3<T> line01 = hPoint0.cross(hPoint1);
623 VectorT3<T> line12 = hPoint1.cross(hPoint2);
624 VectorT3<T> line20 = hPoint2.cross(hPoint0);
625
626 ocean_assert(NumericT<T>::isNotEqualEps(line01.xy().length()));
627 ocean_assert(NumericT<T>::isNotEqualEps(line12.xy().length()));
628 ocean_assert(NumericT<T>::isNotEqualEps(line20.xy().length()));
629
630 // Put each line in n.x + d = 0 form, where n is the unit-length normal pointing away from the
631 // opposite triangle vertex, and d is the signed distance from the origin.
632 line01 /= line01.xy().length();
633 line12 /= line12.xy().length();
634 line20 /= line20.xy().length();
635
636 if (line01 * hPoint2 > T(0.0))
637 {
638 line01 = -line01;
639 line12 = -line12;
640 line20 = -line20;
641 }
642
643 // Shift the lines the specified distance away from the origin.
644 line01.z() -= padWidth;
645 line12.z() -= padWidth;
646 line20.z() -= padWidth;
647
648 // Compute the homogeneous 2D padded triangle vertices as the cross product of the shifted 2D lines.
649 const VectorT3<T> hNewPoint0 = line20.cross(line01);
650 const VectorT3<T> hNewPoint1 = line01.cross(line12);
651 const VectorT3<T> hNewPoint2 = line12.cross(line20);
652
653 // Since the input triangle was valid and the lines stay parallel, it can never be the case that the line intersections are at infinity.
654 ocean_assert(NumericT<T>::isNotEqualEps(hNewPoint0.z()));
655 ocean_assert(NumericT<T>::isNotEqualEps(hNewPoint1.z()));
656 ocean_assert(NumericT<T>::isNotEqualEps(hNewPoint2.z()));
657
658 // De-homogenize.
659 return TriangleT2<T>(
660 VectorT2<T>(hNewPoint0.xy() / hNewPoint0.z()),
661 VectorT2<T>(hNewPoint1.xy() / hNewPoint1.z()),
662 VectorT2<T>(hNewPoint2.xy() / hNewPoint2.z()));
663}
664
665template <typename T>
666inline void TriangleT2<T>::angles(T& angle0, T& angle1, T& angle2) const
667{
668 T cosine0, cosine1, cosine2;
669 cosines(cosine0, cosine1, cosine2);
670
671 angle0 = NumericT<T>::acos(cosine0);
672 angle1 = NumericT<T>::acos(cosine1);
673 angle2 = NumericT<T>::acos(cosine2);
674}
675
676template <typename T>
678{
679 T cosine0, cosine1, cosine2;
680 cosines(cosine0, cosine1, cosine2);
681
682 ocean_assert(NumericT<T>::isInsideRange(T(-1), cosine0, T(1)));
683 ocean_assert(NumericT<T>::isInsideRange(T(-1), cosine1, T(1)));
684 ocean_assert(NumericT<T>::isInsideRange(T(-1), cosine2, T(1)));
685
686 return NumericT<T>::acos(max(NumericT<T>::abs(cosine0), max(NumericT<T>::abs(cosine1), NumericT<T>::abs(cosine2))));
687}
688
689template <typename T>
691{
692 const T sqrLength01(points_[0].sqrDistance(points_[1]));
693 const T sqrLength02(points_[0].sqrDistance(points_[2]));
694 const T sqrLength12(points_[1].sqrDistance(points_[2]));
695
696 return max(sqrLength01, max(sqrLength02, sqrLength12));
697}
698
699template <typename T>
701{
702 return NumericT<T>::sqrt(maxSqrLength());
703}
704
705template <typename T>
707{
708 const T sqrLength01(points_[0].sqrDistance(points_[1]));
709 const T sqrLength02(points_[0].sqrDistance(points_[2]));
710 const T sqrLength12(points_[1].sqrDistance(points_[2]));
711
712 return min(sqrLength01, min(sqrLength02, sqrLength12));
713}
714
715template <typename T>
717{
718 return NumericT<T>::sqrt(minSqrLength());
719}
720
721template <typename T>
722inline bool TriangleT2<T>::isInside(const VectorT2<T>& point) const
723{
724 return TriangleT<T>::isBarycentricInside(cartesian2barycentric(point));
725}
726
727template <typename T>
728inline bool TriangleT2<T>::isInside(const std::vector<TriangleT2<T>>& triangles, const VectorT2<T>& point)
729{
730 for (const TriangleT2<T>& triangle : triangles)
731 {
732 if (triangle.isInside(point))
733 {
734 return true;
735 }
736 }
737
738 return false;
739}
740
741template <typename T>
742inline bool TriangleT2<T>::isCounterClockwise(const bool yAxisDownwards) const
743{
744 ocean_assert(isValid());
745
746 return analyzePoints(points_[0], points_[1], points_[2], yAxisDownwards) < T(0);
747}
748
749template <typename T>
751{
752 ocean_assert_accuracy((std::is_same<float, T>::value || TriangleT<T>::isValidBarycentric(barycentric, NumericT<T>::weakEps())));
753
754 return VectorT2<T>((points_[0].x() * barycentric[0] + points_[1].x() * barycentric[1] + points_[2].x() * barycentric[2]),
755 (points_[0].y() * barycentric[0] + points_[1].y() * barycentric[1] + points_[2].y() * barycentric[2]));
756}
757
758template <typename T>
760{
761 ocean_assert(isValid());
762
763 const T barycentric0 = ((points_[1].y() - points_[2].y()) * (cartesian.x() - points_[2].x())
764 + (points_[2].x() - points_[1].x()) * (cartesian.y() -points_[2].y())) * barycentricFactor_;
765
766 const T barycentric1 = ((points_[2].y() - points_[0].y()) * (cartesian.x() - points_[2].x())
767 + (points_[0].x() - points_[2].x()) * (cartesian.y() - points_[2].y())) * barycentricFactor_;
768
769#ifdef OCEAN_DEBUG
770 if (std::is_same<float, Scalar>::value)
771 {
772 ocean_assert_accuracy(TriangleT<T>::isValidBarycentric(VectorT3<T>(barycentric0, barycentric1, 1 - barycentric0 - barycentric1), NumericT<T>::weakEps()));
773 }
774 else
775 {
776 ocean_assert(TriangleT<T>::isValidBarycentric(VectorT3<T>(barycentric0, barycentric1, 1 - barycentric0 - barycentric1), NumericT<T>::weakEps()));
777 }
778#endif
779
780 return VectorT3<T>(barycentric0, barycentric1, T(1) - barycentric0 - barycentric1);
781}
782
783template <typename T>
785{
786 ocean_assert(isValid());
787 return barycentric2cartesian(barycentricCircumcenter());
788}
789
790template <typename T>
792{
793 ocean_assert(isValid());
794 return barycentric2cartesian(barycentricIncenter());
795}
796
797template <typename T>
798inline bool TriangleT2<T>::isValid() const
799{
800 if (std::is_same<T, double>::value)
801 {
802 return NumericT<T>::isNotEqualEps(barycentricFactor_);
803 }
804 else
805 {
806 return points_[0] != points_[1] && points_[0] != points_[2] && points_[1] != points_[2];
807 }
808}
809
810template <typename T>
811inline const VectorT2<T>& TriangleT2<T>::operator[](const unsigned int index) const
812{
813 ocean_assert(index <= 2u);
814 return points_[index];
815}
816
817template <typename T>
819{
820 return TriangleT2<T>(points_[0] + offset, points_[1] + offset, points_[2] + offset);
821}
822
823template <typename T>
825{
826 points_[0] += offset;
827 points_[1] += offset;
828 points_[2] += offset;
829
830 return *this;
831}
832
833template <typename T>
835{
836 return TriangleT2<T>(points_[0] - offset, points_[1] - offset, points_[2] - offset);
837}
838
839template <typename T>
841{
842 points_[0] -= offset;
843 points_[1] -= offset;
844 points_[2] -= offset;
845
846 return *this;
847}
848
849template <typename T>
850T TriangleT2<T>::analyzePoints(const VectorT2<T>& point0, const VectorT2<T>& point1, const VectorT2<T>& point2, const bool yAxisDownwards)
851{
852 const VectorT2<T> vector01(point1 - point0);
853 const VectorT2<T> vector02(point2 - point0);
854
855 if (yAxisDownwards)
856 {
857 return vector01.cross(vector02);
858 }
859 else
860 {
861 return -vector01.cross(vector02);
862 }
863}
864
865}
866
867#endif // META_OCEAN_MATH_TRIANGLE_H
This class implements an finite line in 2D space.
Definition FiniteLine2.h:82
bool intersects(const FiniteLineT2< T > &second) const
Returns whether two finite lines have a unique intersection point.
Definition FiniteLine2.h:578
This class provides basic numeric functionalities.
Definition Numeric.h:57
static T sqrt(const T value)
Returns the square root of a given value.
Definition Numeric.h:1537
static T acos(const T value)
Returns the arccosine of a given value.
Definition Numeric.h:2916
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition Numeric.h:2246
This class implements a 2D triangle with Cartesian coordinates.
Definition Triangle2.h:81
VectorT3< T > cartesian2barycentric(const VectorT2< T > &cartesian) const
Returns the barycentric coordinate of a given 2D Cartesian coordinate defined in relation to this tri...
Definition Triangle2.h:759
const VectorT2< T > & operator[](const unsigned int index) const
Returns individual triangle corners.
Definition Triangle2.h:811
T maxLength() const
Returns the maximal side length of this triangle.
Definition Triangle2.h:700
TriangleT2< T > & operator+=(const VectorT2< T > &offset)
Shifts the triangle by a given 2D vector (by adding the vector to all three corners of the triangle).
Definition Triangle2.h:824
bool isInside(const VectorT2< T > &point) const
Returns whether a given point lies inside this triangle.
Definition Triangle2.h:722
T sqrDistance01() const
Returns the square distance between point0 and point1.
Definition Triangle2.h:422
T area() const
Returns the area of this triangle.
Definition Triangle2.h:468
TriangleT2< T > operator+(const VectorT2< T > &offset) const
Shifts the triangle by a given 2D vector (by adding the vector to all three corners of the triangle).
Definition Triangle2.h:818
T left() const
Returns the most left position of this triangle.
Definition Triangle2.h:440
TriangleT2< T > & operator-=(const VectorT2< T > &offset)
Shifts the triangle by a given 2D vector (by subtracting the vector from all three corners of the tri...
Definition Triangle2.h:840
T area2() const
Returns the square area of this triangle.
Definition Triangle2.h:474
T minLength() const
Returns the minimal side length of this triangle.
Definition Triangle2.h:716
const VectorT2< T > & point2() const
Returns the third triangle corner.
Definition Triangle2.h:416
bool isCounterClockwise(const bool yAxisDownwards=true) const
Returns whether this triangles is defined in a counter clockwise manner.
Definition Triangle2.h:742
T barycentricFactor_
Convert factor for barycentric coordinates.
Definition Triangle2.h:383
T sqrDistance02() const
Returns the square distance between point0 and point2.
Definition Triangle2.h:428
void angles(T &angle0, T &angle1, T &angle2) const
Calculates the three angles of the three triangle corners.
Definition Triangle2.h:666
VectorT2< T > barycentric2cartesian(const VectorT3< T > &barycentric) const
Returns the 2D Cartesian coordinate of a given barycentric coordinate defined in relation to this tri...
Definition Triangle2.h:750
T top() const
Returns the most top position of this triangle.
Definition Triangle2.h:447
VectorT2< T > cartesianIncenter() const
Returns the incenter for this triangle in Cartesian coordinates.
Definition Triangle2.h:791
bool allCosineBelow(const T cosValue) const
Returns whether all cosine values of the three triangle corners are below or equal to a given thresho...
Definition Triangle2.h:508
T sqrDistance12() const
Returns the square distance between point1 and point2.
Definition Triangle2.h:434
const VectorT2< T > & point0() const
Returns the first triangle corner.
Definition Triangle2.h:404
bool intersects(const TriangleT2< T > &triangle) const
Returns whether this triangle has an intersection with a second triangle.
Definition Triangle2.h:567
static T analyzePoints(const VectorT2< T > &point0, const VectorT2< T > &point1, const VectorT2< T > &point2, const bool yAxisDownwards)
Analyses the layout of three 2D points forming either a triangle or a line.
Definition Triangle2.h:850
void cosines(T &cosine0, T &cosine1, T &cosine2) const
Calculates the three angle cosine values of the three triangle corners.
Definition Triangle2.h:485
T minAngle() const
Returns the minimal angle of this triangle.
Definition Triangle2.h:677
T maxSqrLength() const
Returns the maximal square side length of this triangle.
Definition Triangle2.h:690
VectorT3< T > barycentricIncenter() const
Returns the incenter for this triangle in barycentric coordinates.
Definition Triangle2.h:550
TriangleT2< T > operator-(const VectorT2< T > &offset) const
Shifts the triangle by a given 2D vector (by subtracting the vector from all three corners of the tri...
Definition Triangle2.h:834
T right() const
Returns the most right position of this triangle.
Definition Triangle2.h:454
VectorT3< T > barycentricCircumcenter() const
Returns the circumcenter for this triangle in barycentric coordinates.
Definition Triangle2.h:529
VectorT2< T > cartesianCircumcenter() const
Returns the circumcenter for this triangle in Cartesian coordinates.
Definition Triangle2.h:784
const VectorT2< T > & point1() const
Returns the second triangle corner.
Definition Triangle2.h:410
TriangleT2()=default
Creates a new 2D triangle object with default parameters.
TriangleT2< T > padded(const T padWidth) const
Pad a given 2D triangle along each edge by a fixed value.
Definition Triangle2.h:602
bool isValid() const
Returns whether this triangle can provide valid barycentric coordinates (for 64 bit floating point va...
Definition Triangle2.h:798
T bottom() const
Returns the most bottom position of this triangle.
Definition Triangle2.h:461
VectorT2< T > points_[3]
The corner positions.
Definition Triangle2.h:380
T minSqrLength() const
Returns the minimal square side length of this triangle.
Definition Triangle2.h:706
This class implements a base class for all triangle classes.
Definition Triangle.h:49
static bool isBarycentricInside(const VectorT3< T > &barycentricPoint)
Returns whether a given point, specified as barycentric coordinate, lies inside a triangle.
Definition Triangle.h:69
This class implements a vector with two elements.
Definition Vector2.h:96
const T & x() const noexcept
Returns the x value.
Definition Vector2.h:703
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:715
T sqrDistance(const VectorT2< T > &right) const
Returns the square distance between this 2D position and a second 2D position.
Definition Vector2.h:638
T cross(const VectorT2< T > &vector) const
Returns the cross product of two 2D vectors.
Definition Vector2.h:549
This class implements a vector with three elements.
Definition Vector3.h:97
VectorT3< T > cross(const VectorT3< T > &vector) const
Returns the cross product of two vectors.
Definition Vector3.h:601
VectorT2< T > xy() const noexcept
Returns the x and y component of the vector as new 2D vector.
Definition Vector3.h:840
const T & z() const noexcept
Returns the z value.
Definition Vector3.h:828
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition base/Utilities.h:1159
std::vector< TriangleD2 > TrianglesD2
Definition of a vector holding 2D triangles with double precision float data type.
Definition Triangle2.h:71
std::vector< Triangle2 > Triangles2
Definition of a vector holding 2D triangles.
Definition Triangle2.h:57
std::vector< TriangleT2< T > > TrianglesT2
Definition of a typename alias for vectors with TriangleT2 objects.
Definition Triangle2.h:50
std::vector< TriangleF2 > TrianglesF2
Definition of a vector holding 2D triangles with single precision float data type.
Definition Triangle2.h:64
The namespace covering the entire Ocean framework.
Definition Accessor.h:15