Ocean
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"
12 #include "ocean/math/FiniteLine2.h"
13 #include "ocean/math/Triangle.h"
14 #include "ocean/math/Vector2.h"
15 #include "ocean/math/Vector3.h"
16 
17 namespace Ocean
18 {
19 
20 // Forward declaration.
21 template <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  */
49 template <typename T>
50 using TrianglesT2 = std::vector<TriangleT2<T>>;
51 
52 /**
53  * Definition of a vector holding 2D triangles.
54  * @see Triangle2
55  * @ingroup math
56  */
57 typedef 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  */
64 typedef 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  */
71 typedef 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  */
79 template <typename T>
80 class 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 
385 template <typename T>
386 inline 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 
402 template <typename T>
403 inline const VectorT2<T>& TriangleT2<T>::point0() const
404 {
405  return points_[0];
406 }
407 
408 template <typename T>
409 inline const VectorT2<T>& TriangleT2<T>::point1() const
410 {
411  return points_[1];
412 }
413 
414 template <typename T>
415 inline const VectorT2<T>& TriangleT2<T>::point2() const
416 {
417  return points_[2];
418 }
419 
420 template <typename T>
422 {
423  return points_[0].sqrDistance(points_[1]);
424 }
425 
426 template <typename T>
428 {
429  return points_[0].sqrDistance(points_[2]);
430 }
431 
432 template <typename T>
434 {
435  return points_[1].sqrDistance(points_[2]);
436 }
437 
438 template <typename T>
439 inline 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 
445 template <typename T>
446 inline 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 
452 template <typename T>
453 inline 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 
459 template <typename T>
460 inline 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 
466 template <typename T>
467 inline 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 
482 template <typename T>
483 inline 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 
492 template <typename T>
493 void 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 
512  ocean_assert(NumericT<T>::isWeakEqual(NumericT<T>::acos(cosine0) + NumericT<T>::acos(cosine1) + NumericT<T>::acos(cosine2), NumericT<T>::pi()));
513 }
514 
515 template <typename T>
516 bool 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 
536 template <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 
557 template <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 
574 template <typename T>
575 bool 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 
609 template <typename T>
610 TriangleT2<T> TriangleT2<T>::padded(const T padWidth) const
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 
673 template <typename T>
674 inline 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 
684 template <typename T>
685 inline T TriangleT2<T>::minAngle() const
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 
697 template <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 
707 template <typename T>
708 inline T TriangleT2<T>::maxLength() const
709 {
710  return NumericT<T>::sqrt(maxSqrLength());
711 }
712 
713 template <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 
723 template <typename T>
724 inline T TriangleT2<T>::minLength() const
725 {
726  return NumericT<T>::sqrt(minSqrLength());
727 }
728 
729 template <typename T>
730 inline bool TriangleT2<T>::isInside(const VectorT2<T>& point) const
731 {
732  return TriangleT<T>::isBarycentricInside(cartesian2barycentric(point));
733 }
734 
735 template <typename T>
736 inline 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 
749 template <typename T>
750 inline 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 
757 template <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 
766 template <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 
791 template <typename T>
793 {
794  ocean_assert(isValid());
795  return barycentric2cartesian(barycentricCircumcenter());
796 }
797 
798 template <typename T>
800 {
801  ocean_assert(isValid());
802  return barycentric2cartesian(barycentricIncenter());
803 }
804 
805 template <typename T>
806 inline 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 
818 template <typename T>
819 inline const VectorT2<T>& TriangleT2<T>::operator[](const unsigned int index) const
820 {
821  ocean_assert(index <= 2u);
822  return points_[index];
823 }
824 
825 template <typename T>
827 {
828  return TriangleT2<T>(points_[0] + offset, points_[1] + offset, points_[2] + offset);
829 }
830 
831 template <typename T>
833 {
834  points_[0] += offset;
835  points_[1] += offset;
836  points_[2] += offset;
837 
838  return *this;
839 }
840 
841 template <typename T>
843 {
844  return TriangleT2<T>(points_[0] - offset, points_[1] - offset, points_[2] - offset);
845 }
846 
847 template <typename T>
849 {
850  points_[0] -= offset;
851  points_[1] -= offset;
852  points_[2] -= offset;
853 
854  return *this;
855 }
856 
857 template <typename T>
858 T 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:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
T cross(const VectorT2< T > &vector) const
Returns the cross product of two 2D vectors.
Definition: Vector2.h:544
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:597
VectorT2< T > xy() const noexcept
Returns the x and y component of the vector as new 2D vector.
Definition: Vector3.h:836
const T & z() const noexcept
Returns the z value.
Definition: Vector3.h:824
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:21
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