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 */
57typedef std::vector<Triangle2> Triangles2;
58
59/**
60 * Definition of a vector holding 2D triangles with single precision float data type.
61 * @see Triangle2
62 * @ingroup math
63 */
64typedef std::vector<TriangleF2> TrianglesF2;
65
66/**
67 * Definition of a vector holding 2D triangles with double precision float data type.
68 * @see Triangle2
69 * @ingroup math
70 */
71typedef std::vector<TriangleD2> TrianglesD2;
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 * @return Triangle area
167 * @see area().
168 */
169 inline T area2() const;
170
171 /**
172 * Calculates the three angle cosine values of the three triangle corners.
173 * Beware: Make sure that this triangle is valid before!
174 * @param cosine0 Resulting angle corresponding to point0
175 * @param cosine1 Resulting angle corresponding to point1
176 * @param cosine2 Resulting angle corresponding to point2
177 */
178 void cosines(T& cosine0, T& cosine1, T& cosine2) const;
179
180 /**
181 * Calculates the three angles of the three triangle corners.
182 * Beware: Make sure that this triangle is valid before!
183 * @param angle0 Resulting angle corresponding to point0 in radian
184 * @param angle1 Resulting angle corresponding to point1 in radian
185 * @param angle2 Resulting angle corresponding to point2 in radian
186 */
187 inline void angles(T& angle0, T& angle1, T& angle2) const;
188
189 /**
190 * Returns the minimal angle of this triangle.
191 * Beware: Make sure that this triangle is valid before!
192 * @return Minimal angle in radian
193 */
194 inline T minAngle() const;
195
196 /**
197 * Returns whether all cosine values of the three triangle corners are below or equal to a given threshold.
198 * Thus, to test whether the minimal corner angle is equal to PI/8, then allCosineBelow(cos(PI/8)) has to be checked.
199 * @param cosValue Cosine threshold value
200 * @return True, if so
201 */
202 bool allCosineBelow(const T cosValue) const;
203
204 /**
205 * Returns the maximal square side length of this triangle.
206 * @return Maximal square side length
207 */
208 inline T maxSqrLength() const;
209
210 /**
211 * Returns the maximal side length of this triangle.
212 * @return Maximal side length
213 */
214 inline T maxLength() const;
215
216 /**
217 * Returns the minimal square side length of this triangle.
218 * @return Minimal square side length
219 */
220 inline T minSqrLength() const;
221
222 /**
223 * Returns the minimal side length of this triangle.
224 * @return Minimal side length
225 */
226 inline T minLength() const;
227
228 /**
229 * Returns whether a given point lies inside this triangle.
230 * @param point The point to be checked
231 * @return True, if so
232 */
233 inline bool isInside(const VectorT2<T>& point) const;
234
235 /**
236 * Returns whether a given point lies inside at least one of the given triangles.
237 * @param triangles The triangles that are tested
238 * @param point The point to be checked
239 * @return True, if so
240 */
241 static inline bool isInside(const std::vector<TriangleT2<T>>& triangles, const VectorT2<T>& point);
242
243 /**
244 * Returns whether this triangles is defined in a counter clockwise manner.
245 * The result of the function depends on the coordinate system in which the points are defined:
246 * <pre>
247 * First coordinate system, Second coordinate system
248 *
249 * ------> x-axis ^
250 * | | y-axis
251 * | |
252 * | y-axis |
253 * V ------> x-axis
254 *
255 * </pre>
256 * @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
257 * @return True, if so
258 */
259 inline bool isCounterClockwise(const bool yAxisDownwards = true) const;
260
261 /**
262 * Returns the 2D Cartesian coordinate of a given barycentric coordinate defined in relation to this triangle.
263 * @param barycentric The Barycentric coordinate to convert to a Cartesian coordinate
264 * @return Cartesian coordinate
265 */
266 inline VectorT2<T> barycentric2cartesian(const VectorT3<T>& barycentric) const;
267
268 /**
269 * Returns the barycentric coordinate of a given 2D Cartesian coordinate defined in relation to this triangle.
270 * @param cartesian The Cartesian coordinate to convert to a barycentric coordinate
271 * @return Barycentric coordinate
272 */
273 inline VectorT3<T> cartesian2barycentric(const VectorT2<T>& cartesian) const;
274
275 /**
276 * Returns the circumcenter for this triangle in barycentric coordinates.
277 * @return Barycentric coordinates of the circumcenter
278 */
280
281 /**
282 * Returns the circumcenter for this triangle in Cartesian coordinates.
283 * @return Cartesian coordinates of the circumcenter
284 */
285 inline VectorT2<T> cartesianCircumcenter() const;
286
287 /**
288 * Returns the incenter for this triangle in barycentric coordinates.
289 * @return Barycentric coordinates of the incenter
290 */
292
293 /**
294 * Returns the incenter for this triangle in Cartesian coordinates.
295 * @return Cartesian coordinates of the circumcenter
296 */
297 inline VectorT2<T> cartesianIncenter() const;
298
299 /**
300 * Returns whether this triangle has an intersection with a second triangle.
301 * @param triangle The second triangle to test
302 * @return True, if so
303 */
304 bool intersects(const TriangleT2<T>& triangle) const;
305
306 /**
307 * 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.
308 * @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
309 * @return Padded 2D triangle
310 */
311 TriangleT2<T> padded(const T padWidth) const;
312
313 /**
314 * Returns whether this triangle can provide valid barycentric coordinates (for 64 bit floating point values).
315 * For 32 bit floating point values we simply check whether all three corners of the triangle are different.
316 * @return True, if so
317 */
318 inline bool isValid() const;
319
320 /**
321 * Returns individual triangle corners.
322 * @param index Index of the corner that is requested, with range [0, 2]
323 * @return Resulting triangle corner
324 */
325 inline const VectorT2<T>& operator[](const unsigned int index) const;
326
327 /**
328 * Shifts the triangle by a given 2D vector (by adding the vector to all three corners of the triangle).
329 * @param offset The offset vector to shift the triangle
330 * @return The new shifted triangle
331 */
332 inline TriangleT2<T> operator+(const VectorT2<T>& offset) const;
333
334 /**
335 * Shifts the triangle by a given 2D vector (by adding the vector to all three corners of the triangle).
336 * @param offset The offset vector to shift the triangle
337 * @return The reference to this triangle
338 */
339 inline TriangleT2<T>& operator+=(const VectorT2<T>& offset);
340
341 /**
342 * Shifts the triangle by a given 2D vector (by subtracting the vector from all three corners of the triangle).
343 * @param offset The offset vector to shift the triangle
344 * @return The new shifted triangle
345 */
346 inline TriangleT2<T> operator-(const VectorT2<T>& offset) const;
347
348 /**
349 * Shifts the triangle by a given 2D vector (by subtracting the vector from all three corners of the triangle).
350 * @param offset The offset vector to shift the triangle
351 * @return The reference to this triangle
352 */
353 inline TriangleT2<T>& operator-=(const VectorT2<T>& offset);
354
355 /**
356 * Analyses the layout of three 2D points forming either a triangle or a line.
357 * The result of the function depends on the coordinate system in which the points are defined:
358 * <pre>
359 * First coordinate system, Second coordinate system
360 *
361 * ------> x-axis ^
362 * | | y-axis
363 * | |
364 * | y-axis |
365 * V ------> x-axis
366 *
367 * </pre>
368 * @param point0 The first point to be analyzed
369 * @param point1 The first point to be analyzed
370 * @param point2 The first point to be analyzed
371 * @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
372 * @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)
373 */
374 static T analyzePoints(const VectorT2<T>& point0, const VectorT2<T>& point1, const VectorT2<T>& point2, const bool yAxisDownwards);
375
376 private:
377
378 /// The corner positions.
379 VectorT2<T> points_[3] = {VectorT2<T>(T(0), T(0)), VectorT2<T>(T(0), T(0)), VectorT2<T>(T(0), T(0))};
380
381 /// Convert factor for barycentric coordinates.
383};
384
385template <typename T>
386inline TriangleT2<T>::TriangleT2(const VectorT2<T>& point0, const VectorT2<T>& point1, const VectorT2<T>& point2) :
387 barycentricFactor_(T(0))
388{
389 points_[0] = point0;
390 points_[1] = point1;
391 points_[2] = point2;
392
393 const T factor = (points_[1].y() - points_[2].y()) * (points_[0].x() - points_[2].x())
394 + (points_[2].x() - points_[1].x()) * (points_[0].y() - points_[2].y());
395
396 if (NumericT<T>::isNotEqualEps(factor))
397 {
398 barycentricFactor_ = T(1) / factor;
399 }
400}
401
402template <typename T>
404{
405 return points_[0];
406}
407
408template <typename T>
410{
411 return points_[1];
412}
413
414template <typename T>
416{
417 return points_[2];
418}
419
420template <typename T>
422{
423 return points_[0].sqrDistance(points_[1]);
424}
425
426template <typename T>
428{
429 return points_[0].sqrDistance(points_[2]);
430}
431
432template <typename T>
434{
435 return points_[1].sqrDistance(points_[2]);
436}
437
438template <typename T>
439inline T TriangleT2<T>::left() const
440{
441 ocean_assert(isValid());
442 return min(points_[0].x(), min(points_[1].x(), points_[2].x()));
443}
444
445template <typename T>
446inline T TriangleT2<T>::top() const
447{
448 ocean_assert(isValid());
449 return min(points_[0].y(), min(points_[1].y(), points_[2].y()));
450}
451
452template <typename T>
453inline T TriangleT2<T>::right() const
454{
455 ocean_assert(isValid());
456 return max(points_[0].x(), max(points_[1].x(), points_[2].x()));
457}
458
459template <typename T>
460inline T TriangleT2<T>::bottom() const
461{
462 ocean_assert(isValid());
463 return max(points_[0].y(), max(points_[1].y(), points_[2].y()));
464}
465
466template <typename T>
467inline T TriangleT2<T>::area() const
468{
469 const T squaredArea = area2();
470
471 if (std::is_same<T, float>::value)
472 {
473 if (squaredArea <= T(0))
474 {
475 return T(0);
476 }
477 }
478
479 return NumericT<T>::sqrt(area2());
480}
481
482template <typename T>
483inline T TriangleT2<T>::area2() const
484{
485 const T a2 = points_[0].sqrDistance(points_[1]);
486 const T b2 = points_[0].sqrDistance(points_[2]);
487 const T c2 = points_[1].sqrDistance(points_[2]);
488
489 return (T(4) * a2 * c2 - NumericT<T>::sqr(a2 + c2 - b2)) * T(0.0625);
490}
491
492template <typename T>
493void TriangleT2<T>::cosines(T& cosine0, T& cosine1, T& cosine2) const
494{
495 ocean_assert(isValid());
496
497 const T sqrDistance01(points_[1].sqrDistance(points_[0]));
498 const T sqrDistance02(points_[2].sqrDistance(points_[0]));
499 const T sqrDistance12(points_[2].sqrDistance(points_[1]));
500
501 const T factorDistance01(T(1) / NumericT<T>::sqrt(sqrDistance01));
502 const T factorDistance02(T(1) / NumericT<T>::sqrt(sqrDistance02));
503 const T factorDistance12(T(1) / NumericT<T>::sqrt(sqrDistance12));
504
505 // c^2 = a^2 + b^2 - 2abcos
506 // cos = (a^2 + b^2 - c^2) / (2ab)
507
508 cosine0 = (sqrDistance01 + sqrDistance02 - sqrDistance12) * T(0.5) * factorDistance01 * factorDistance02;
509 cosine1 = (sqrDistance01 + sqrDistance12 - sqrDistance02) * T(0.5) * factorDistance01 * factorDistance12;
510 cosine2 = (sqrDistance02 + sqrDistance12 - sqrDistance01) * T(0.5) * factorDistance02 * factorDistance12;
511
513}
514
515template <typename T>
516bool TriangleT2<T>::allCosineBelow(const T cosValue) const
517{
518 ocean_assert(isValid());
519
520 const T sqrDistance01(points_[1].sqrDistance(points_[0]));
521 const T sqrDistance02(points_[2].sqrDistance(points_[0]));
522 const T sqrDistance12(points_[2].sqrDistance(points_[1]));
523
524 const T factorDistance01(T(1) / NumericT<T>::sqrt(sqrDistance01));
525 const T factorDistance02(T(1) / NumericT<T>::sqrt(sqrDistance02));
526 const T factorDistance12(T(1) / NumericT<T>::sqrt(sqrDistance12));
527
528 // c^2 = a^2 + b^2 - 2abcos
529 // cos = (a^2 + b^2 - c^2) / (2ab)
530
531 return (sqrDistance01 + sqrDistance02 - sqrDistance12) * T(0.5) * factorDistance01 * factorDistance02 <= cosValue
532 && (sqrDistance01 + sqrDistance12 - sqrDistance02) * T(0.5) * factorDistance01 * factorDistance12 <= cosValue
533 && (sqrDistance02 + sqrDistance12 - sqrDistance01) * T(0.5) * factorDistance02 * factorDistance12 <= cosValue;
534}
535
536template <typename T>
538{
539 ocean_assert(isValid());
540
541 const T a2 = points_[1].sqrDistance(points_[2]);
542 const T b2 = points_[0].sqrDistance(points_[2]);
543 const T c2 = points_[0].sqrDistance(points_[1]);
544
545 const T coord0 = a2 * (-a2 + b2 + c2);
546 const T coord1 = b2 * (a2 - b2 + c2);
547 const T coord2 = c2 * (a2 + b2 - c2);
548
549 const T total = coord0 + coord1 + coord2;
550 ocean_assert(NumericT<T>::isNotEqualEps(total));
551
552 const T factor = T(1) / total;
553
554 return VectorT3<T>(coord0 * factor, coord1 * factor, coord2 * factor);
555}
556
557template <typename T>
559{
560 ocean_assert(isValid());
561
562 const T a = points_[1].distance(points_[2]);
563 const T b = points_[0].distance(points_[2]);
564 const T c = points_[0].distance(points_[1]);
565
566 const T total = a + b + c;
567 ocean_assert(NumericT<T>::isNotEqualEps(total));
568
569 const T factor = T(1) / total;
570
571 return VectorT3<T>(a * factor, b * factor, c * factor);
572}
573
574template <typename T>
575bool TriangleT2<T>::intersects(const TriangleT2<T>& triangle) const
576{
577 ocean_assert(isValid() && triangle.isValid());
578
579 // check whether bounding boxes do not intersect
580 if (left() > triangle.right() || triangle.left() > right() || top() > triangle.bottom() || triangle.top() > bottom())
581 {
582 return false;
583 }
584
585 if (isInside(triangle.point0()) || isInside(triangle.point1()) || isInside(triangle.point2()) || triangle.isInside(point0()) || triangle.isInside(point1()) || triangle.isInside(point2()))
586 {
587 return true;
588 }
589
590 const FiniteLineT2<T> thisLines[3] =
591 {
592 FiniteLineT2<T>(point0(), point1()),
593 FiniteLineT2<T>(point1(), point2()),
594 FiniteLineT2<T>(point2(), point0())
595 };
596
597 const FiniteLineT2<T> triangleLines[3] =
598 {
599 FiniteLineT2<T>(triangle.point0(), triangle.point1()),
600 FiniteLineT2<T>(triangle.point1(), triangle.point2()),
601 FiniteLineT2<T>(triangle.point2(), triangle.point0())
602 };
603
604 return thisLines[0].intersects(triangleLines[0]) || thisLines[0].intersects(triangleLines[1]) || thisLines[0].intersects(triangleLines[2])
605 || thisLines[1].intersects(triangleLines[0]) || thisLines[1].intersects(triangleLines[1]) || thisLines[1].intersects(triangleLines[2])
606 || thisLines[2].intersects(triangleLines[0]) || thisLines[2].intersects(triangleLines[1]) || thisLines[2].intersects(triangleLines[2]);
607}
608
609template <typename T>
611{
612 ocean_assert(isValid());
613 ocean_assert(NumericT<T>::isNotEqualEps(padWidth));
614
615 if (!isValid())
616 {
617 return TriangleT2<T>();
618 }
619
620 if (NumericT<T>::isEqualEps(padWidth))
621 {
622 return *this;
623 }
624
625 // Create homogeneous 2D points.
626 const VectorT3<T> hPoint0(points_[0], T(1.0));
627 const VectorT3<T> hPoint1(points_[1], T(1.0));
628 const VectorT3<T> hPoint2(points_[2], T(1.0));
629
630 VectorT3<T> line01 = hPoint0.cross(hPoint1);
631 VectorT3<T> line12 = hPoint1.cross(hPoint2);
632 VectorT3<T> line20 = hPoint2.cross(hPoint0);
633
634 ocean_assert(NumericT<T>::isNotEqualEps(line01.xy().length()));
635 ocean_assert(NumericT<T>::isNotEqualEps(line12.xy().length()));
636 ocean_assert(NumericT<T>::isNotEqualEps(line20.xy().length()));
637
638 // Put each line in n.x + d = 0 form, where n is the unit-length normal pointing away from the
639 // opposite triangle vertex, and d is the signed distance from the origin.
640 line01 /= line01.xy().length();
641 line12 /= line12.xy().length();
642 line20 /= line20.xy().length();
643
644 if (line01 * hPoint2 > T(0.0))
645 {
646 line01 = -line01;
647 line12 = -line12;
648 line20 = -line20;
649 }
650
651 // Shift the lines the specified distance away from the origin.
652 line01.z() -= padWidth;
653 line12.z() -= padWidth;
654 line20.z() -= padWidth;
655
656 // Compute the homogeneous 2D padded triangle vertices as the cross product of the shifted 2D lines.
657 const VectorT3<T> hNewPoint0 = line20.cross(line01);
658 const VectorT3<T> hNewPoint1 = line01.cross(line12);
659 const VectorT3<T> hNewPoint2 = line12.cross(line20);
660
661 // Since the input triangle was valid and the lines stay parallel, it can never be the case that the line intersections are at infinity.
662 ocean_assert(NumericT<T>::isNotEqualEps(hNewPoint0.z()));
663 ocean_assert(NumericT<T>::isNotEqualEps(hNewPoint1.z()));
664 ocean_assert(NumericT<T>::isNotEqualEps(hNewPoint2.z()));
665
666 // De-homogenize.
667 return TriangleT2<T>(
668 VectorT2<T>(hNewPoint0.xy() / hNewPoint0.z()),
669 VectorT2<T>(hNewPoint1.xy() / hNewPoint1.z()),
670 VectorT2<T>(hNewPoint2.xy() / hNewPoint2.z()));
671}
672
673template <typename T>
674inline void TriangleT2<T>::angles(T& angle0, T& angle1, T& angle2) const
675{
676 T cosine0, cosine1, cosine2;
677 cosines(cosine0, cosine1, cosine2);
678
679 angle0 = NumericT<T>::acos(cosine0);
680 angle1 = NumericT<T>::acos(cosine1);
681 angle2 = NumericT<T>::acos(cosine2);
682}
683
684template <typename T>
686{
687 T cosine0, cosine1, cosine2;
688 cosines(cosine0, cosine1, cosine2);
689
690 ocean_assert(NumericT<T>::isInsideRange(T(-1), cosine0, T(1)));
691 ocean_assert(NumericT<T>::isInsideRange(T(-1), cosine1, T(1)));
692 ocean_assert(NumericT<T>::isInsideRange(T(-1), cosine2, T(1)));
693
694 return NumericT<T>::acos(max(NumericT<T>::abs(cosine0), max(NumericT<T>::abs(cosine1), NumericT<T>::abs(cosine2))));
695}
696
697template <typename T>
699{
700 const T sqrLength01(points_[0].sqrDistance(points_[1]));
701 const T sqrLength02(points_[0].sqrDistance(points_[2]));
702 const T sqrLength12(points_[1].sqrDistance(points_[2]));
703
704 return max(sqrLength01, max(sqrLength02, sqrLength12));
705}
706
707template <typename T>
709{
710 return NumericT<T>::sqrt(maxSqrLength());
711}
712
713template <typename T>
715{
716 const T sqrLength01(points_[0].sqrDistance(points_[1]));
717 const T sqrLength02(points_[0].sqrDistance(points_[2]));
718 const T sqrLength12(points_[1].sqrDistance(points_[2]));
719
720 return min(sqrLength01, min(sqrLength02, sqrLength12));
721}
722
723template <typename T>
725{
726 return NumericT<T>::sqrt(minSqrLength());
727}
728
729template <typename T>
730inline bool TriangleT2<T>::isInside(const VectorT2<T>& point) const
731{
732 return TriangleT<T>::isBarycentricInside(cartesian2barycentric(point));
733}
734
735template <typename T>
736inline bool TriangleT2<T>::isInside(const std::vector<TriangleT2<T>>& triangles, const VectorT2<T>& point)
737{
738 for (const TriangleT2<T>& triangle : triangles)
739 {
740 if (triangle.isInside(point))
741 {
742 return true;
743 }
744 }
745
746 return false;
747}
748
749template <typename T>
750inline bool TriangleT2<T>::isCounterClockwise(const bool yAxisDownwards) const
751{
752 ocean_assert(isValid());
753
754 return analyzePoints(points_[0], points_[1], points_[2], yAxisDownwards) < T(0);
755}
756
757template <typename T>
759{
760 ocean_assert_accuracy((std::is_same<float, T>::value || TriangleT<T>::isValidBarycentric(barycentric, NumericT<T>::weakEps())));
761
762 return VectorT2<T>((points_[0].x() * barycentric[0] + points_[1].x() * barycentric[1] + points_[2].x() * barycentric[2]),
763 (points_[0].y() * barycentric[0] + points_[1].y() * barycentric[1] + points_[2].y() * barycentric[2]));
764}
765
766template <typename T>
768{
769 ocean_assert(isValid());
770
771 const T barycentric0 = ((points_[1].y() - points_[2].y()) * (cartesian.x() - points_[2].x())
772 + (points_[2].x() - points_[1].x()) * (cartesian.y() -points_[2].y())) * barycentricFactor_;
773
774 const T barycentric1 = ((points_[2].y() - points_[0].y()) * (cartesian.x() - points_[2].x())
775 + (points_[0].x() - points_[2].x()) * (cartesian.y() - points_[2].y())) * barycentricFactor_;
776
777#ifdef OCEAN_DEBUG
778 if (std::is_same<float, Scalar>::value)
779 {
780 ocean_assert_accuracy(TriangleT<T>::isValidBarycentric(VectorT3<T>(barycentric0, barycentric1, 1 - barycentric0 - barycentric1), NumericT<T>::weakEps()));
781 }
782 else
783 {
784 ocean_assert(TriangleT<T>::isValidBarycentric(VectorT3<T>(barycentric0, barycentric1, 1 - barycentric0 - barycentric1), NumericT<T>::weakEps()));
785 }
786#endif
787
788 return VectorT3<T>(barycentric0, barycentric1, T(1) - barycentric0 - barycentric1);
789}
790
791template <typename T>
793{
794 ocean_assert(isValid());
795 return barycentric2cartesian(barycentricCircumcenter());
796}
797
798template <typename T>
800{
801 ocean_assert(isValid());
802 return barycentric2cartesian(barycentricIncenter());
803}
804
805template <typename T>
806inline bool TriangleT2<T>::isValid() const
807{
808 if (std::is_same<T, double>::value)
809 {
810 return NumericT<T>::isNotEqualEps(barycentricFactor_);
811 }
812 else
813 {
814 return points_[0] != points_[1] && points_[0] != points_[2] && points_[1] != points_[2];
815 }
816}
817
818template <typename T>
819inline const VectorT2<T>& TriangleT2<T>::operator[](const unsigned int index) const
820{
821 ocean_assert(index <= 2u);
822 return points_[index];
823}
824
825template <typename T>
827{
828 return TriangleT2<T>(points_[0] + offset, points_[1] + offset, points_[2] + offset);
829}
830
831template <typename T>
833{
834 points_[0] += offset;
835 points_[1] += offset;
836 points_[2] += offset;
837
838 return *this;
839}
840
841template <typename T>
843{
844 return TriangleT2<T>(points_[0] - offset, points_[1] - offset, points_[2] - offset);
845}
846
847template <typename T>
849{
850 points_[0] -= offset;
851 points_[1] -= offset;
852 points_[2] -= offset;
853
854 return *this;
855}
856
857template <typename T>
858T TriangleT2<T>::analyzePoints(const VectorT2<T>& point0, const VectorT2<T>& point1, const VectorT2<T>& point2, const bool yAxisDownwards)
859{
860 const VectorT2<T> vector01(point1 - point0);
861 const VectorT2<T> vector02(point2 - point0);
862
863 if (yAxisDownwards)
864 {
865 return vector01.cross(vector02);
866 }
867 else
868 {
869 return -vector01.cross(vector02);
870 }
871}
872
873}
874
875#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:1533
static T acos(const T value)
Returns the arccosine of a given value.
Definition Numeric.h:2907
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition Numeric.h:2237
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:767
const VectorT2< T > & operator[](const unsigned int index) const
Returns individual triangle corners.
Definition Triangle2.h:819
T maxLength() const
Returns the maximal side length of this triangle.
Definition Triangle2.h:708
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:832
bool isInside(const VectorT2< T > &point) const
Returns whether a given point lies inside this triangle.
Definition Triangle2.h:730
T sqrDistance01() const
Returns the square distance between point0 and point1.
Definition Triangle2.h:421
T area() const
Returns the area of this triangle.
Definition Triangle2.h:467
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:826
T left() const
Returns the most left position of this triangle.
Definition Triangle2.h:439
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:848
T area2() const
Returns the square area of this triangle.
Definition Triangle2.h:483
T minLength() const
Returns the minimal side length of this triangle.
Definition Triangle2.h:724
const VectorT2< T > & point2() const
Returns the third triangle corner.
Definition Triangle2.h:415
bool isCounterClockwise(const bool yAxisDownwards=true) const
Returns whether this triangles is defined in a counter clockwise manner.
Definition Triangle2.h:750
T barycentricFactor_
Convert factor for barycentric coordinates.
Definition Triangle2.h:382
T sqrDistance02() const
Returns the square distance between point0 and point2.
Definition Triangle2.h:427
void angles(T &angle0, T &angle1, T &angle2) const
Calculates the three angles of the three triangle corners.
Definition Triangle2.h:674
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:758
T top() const
Returns the most top position of this triangle.
Definition Triangle2.h:446
VectorT2< T > cartesianIncenter() const
Returns the incenter for this triangle in Cartesian coordinates.
Definition Triangle2.h:799
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:516
T sqrDistance12() const
Returns the square distance between point1 and point2.
Definition Triangle2.h:433
const VectorT2< T > & point0() const
Returns the first triangle corner.
Definition Triangle2.h:403
bool intersects(const TriangleT2< T > &triangle) const
Returns whether this triangle has an intersection with a second triangle.
Definition Triangle2.h:575
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:858
void cosines(T &cosine0, T &cosine1, T &cosine2) const
Calculates the three angle cosine values of the three triangle corners.
Definition Triangle2.h:493
T minAngle() const
Returns the minimal angle of this triangle.
Definition Triangle2.h:685
T maxSqrLength() const
Returns the maximal square side length of this triangle.
Definition Triangle2.h:698
VectorT3< T > barycentricIncenter() const
Returns the incenter for this triangle in barycentric coordinates.
Definition Triangle2.h:558
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:842
T right() const
Returns the most right position of this triangle.
Definition Triangle2.h:453
VectorT3< T > barycentricCircumcenter() const
Returns the circumcenter for this triangle in barycentric coordinates.
Definition Triangle2.h:537
VectorT2< T > cartesianCircumcenter() const
Returns the circumcenter for this triangle in Cartesian coordinates.
Definition Triangle2.h:792
const VectorT2< T > & point1() const
Returns the second triangle corner.
Definition Triangle2.h:409
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:610
bool isValid() const
Returns whether this triangle can provide valid barycentric coordinates (for 64 bit floating point va...
Definition Triangle2.h:806
T bottom() const
Returns the most bottom position of this triangle.
Definition Triangle2.h:460
VectorT2< T > points_[3]
The corner positions.
Definition Triangle2.h:379
T minSqrLength() const
Returns the minimal square side length of this triangle.
Definition Triangle2.h:714
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:710
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:722
T sqrDistance(const VectorT2< T > &right) const
Returns the square distance between this 2D position and a second 2D position.
Definition Vector2.h:645
T cross(const VectorT2< T > &vector) const
Returns the cross product of two 2D vectors.
Definition Vector2.h:556
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:609
VectorT2< T > xy() const noexcept
Returns the x and y component of the vector as new 2D vector.
Definition Vector3.h:848
const T & z() const noexcept
Returns the z value.
Definition Vector3.h:836
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition base/Utilities.h:1089
std::vector< Triangle2 > Triangles2
Definition of a vector holding 2D triangles.
Definition Triangle2.h:57
TriangleT2< Scalar > Triangle2
Definition of the Triangle2 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with sing...
Definition Triangle2.h:28
std::vector< TriangleF2 > TrianglesF2
Definition of a vector holding 2D triangles with single precision float data type.
Definition Triangle2.h:64
std::vector< TriangleD2 > TrianglesD2
Definition of a vector holding 2D triangles with double precision float data type.
Definition Triangle2.h:71
std::vector< TriangleT2< T > > TrianglesT2
Definition of a typename alias for vectors with TriangleT2 objects.
Definition Triangle2.h:50
TriangleT2< float > TriangleF2
Instantiation of the TriangleT2 template class using a single precision float data type.
Definition Triangle2.h:42
TriangleT2< double > TriangleD2
Instantiation of the TriangleT2 template class using a double precision float data type.
Definition Triangle2.h:35
The namespace covering the entire Ocean framework.
Definition Accessor.h:15