MeshLib
 
Loading...
Searching...
No Matches
MRTriMath.h
Go to the documentation of this file.
1#pragma once
2// triangle-related mathematical functions are here
3
4#include "MRVector3.h"
5#include <algorithm>
6#include <cmath>
7#include <limits>
8#include <optional>
9
10namespace MR
11{
12
15template <typename T>
16[[nodiscard]] T circumcircleDiameterSq( const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c )
17{
18 const auto ab = ( b - a ).lengthSq();
19 const auto ca = ( a - c ).lengthSq();
20 const auto bc = ( c - b ).lengthSq();
21 if ( ab <= 0 )
22 return ca;
23 if ( ca <= 0 )
24 return bc;
25 if ( bc <= 0 )
26 return ab;
27 const auto f = cross( b - a, c - a ).lengthSq();
28 if ( f <= 0 )
29 return std::numeric_limits<T>::infinity();
30 return ab * ca * bc / f;
31}
32
35template <typename T>
36[[nodiscard]] inline T circumcircleDiameter( const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c )
37{
38 return std::sqrt( circumcircleDiameterSq( a, b, c ) );
39}
40
42template <typename T>
43[[nodiscard]] Vector3<T> circumcircleCenter( const Vector3<T> & a, const Vector3<T> & b )
44{
45 const auto xabSq = cross( a, b ).lengthSq();
46 const auto aa = a.lengthSq();
47 const auto bb = b.lengthSq();
48 if ( xabSq <= 0 )
49 {
50 if ( aa <= 0 )
51 return b / T(2);
52 // else b == 0 || a == b
53 return a / T(2);
54 }
55 const auto ab = dot( a, b );
56 return ( bb * ( aa - ab ) * a + aa * ( bb - ab ) * b ) / ( 2 * xabSq );
57}
58
60template <typename T>
61[[nodiscard]] inline Vector3<T> circumcircleCenter( const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c )
62{
63 return circumcircleCenter( a - c, b - c ) + c;
64}
65
68template <typename T>
69[[nodiscard]] bool circumballCenters( const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c, T radius,
70 Vector3<T> & centerPos, // ball's center from the positive side of triangle
71 Vector3<T> & centerNeg )// ball's center from the negative side of triangle
72{
73 const auto rr = sqr( radius );
74 const auto circRadSq = circumcircleDiameterSq( a, b, c ) / T( 4 );
75 if ( rr < circRadSq )
76 return false;
77
78 const auto x = std::sqrt( rr - circRadSq );
79 const auto xn = x * normal( a, b, c );
80 const auto circCenter = circumcircleCenter( a, b, c );
81 centerPos = circCenter + xn;
82 centerNeg = circCenter - xn;
83
84 return true;
85}
86
89template <typename T>
90[[nodiscard]] T minTriangleAngleSin( const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c )
91{
92 const auto ab = ( b - a ).length();
93 const auto ca = ( a - c ).length();
94 const auto bc = ( c - b ).length();
95 if ( ab <= 0 || ca <= 0 || bc <= 0 )
96 return 0;
97 const auto f = cross( b - a, c - a ).length();
98 return f * std::min( { ab, ca, bc } ) / ( ab * ca * bc );
99}
100
101template <typename T>
102[[nodiscard]] T minTriangleAngle( const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c )
103{
104 return std::asin( minTriangleAngleSin( a, b, c ) );
105}
106
109template<typename T>
110[[nodiscard]] T triangleAspectRatio( const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c )
111{
112 const auto bc = ( c - b ).length();
113 const auto ca = ( a - c ).length();
114 const auto ab = ( b - a ).length();
115 auto halfPerimeter = ( bc + ca + ab ) / 2;
116 auto den = 8 * ( halfPerimeter - bc ) * ( halfPerimeter - ca ) * ( halfPerimeter - ab );
117 if ( den <= 0 )
118 return std::numeric_limits<T>::max();
119
120 return bc * ca * ab / den;
121}
122
124template<typename T>
125[[nodiscard]] inline Vector3<T> dirDblArea( const Triangle3<T> & t )
126{
127 return cross( t[1] - t[0], t[2] - t[0] );
128}
129
131template<typename T>
132[[nodiscard]] inline Vector3<T> dirDblArea( const Vector3<T> & p, const Vector3<T> & q, const Vector3<T> & r )
133{
134 return cross( q - p, r - p );
135}
136
138template<typename T>
139[[nodiscard]] inline Vector3<T> normal( const Vector3<T> & p, const Vector3<T> & q, const Vector3<T> & r )
140{
141 return dirDblArea( p, q, r ).normalized();
142}
143
145template<typename T>
146[[nodiscard]] inline T dblAreaSq( const Vector3<T> & p, const Vector3<T> & q, const Vector3<T> & r )
147{
148 return dirDblArea( p, q, r ).lengthSq();
149}
150
152template<typename T>
153[[nodiscard]] inline T dblArea( const Vector3<T> & p, const Vector3<T> & q, const Vector3<T> & r )
154{
155 return dirDblArea( p, q, r ).length();
156}
157
159template<typename T>
160[[nodiscard]] inline T area( const Vector3<T> & p, const Vector3<T> & q, const Vector3<T> & r )
161{
162 return dblArea( p, q, r ) / 2;
163}
164
166template<typename T>
167[[nodiscard]] inline T dblArea( const Vector2<T> & p, const Vector2<T> & q, const Vector2<T> & r )
168{
169 return std::abs( cross( q - p, r - p ) );
170}
171
173template<typename T>
174[[nodiscard]] inline T area( const Vector2<T> & p, const Vector2<T> & q, const Vector2<T> & r )
175{
176 return dblArea( p, q, r ) / 2;
177}
178
180template <typename T>
181[[nodiscard]] Triangle3<T> makeDegenerate( const Triangle3<T> & t )
182{
183 const auto c = ( t[0] + t[1] + t[2] ) / T(3);
184 int longest = 0;
185 T longestSq = 0;
186 for ( int i = 0; i < 3; ++i )
187 {
188 const auto sq = ( t[i] - c ).lengthSq();
189 if ( longestSq >= sq )
190 continue;
191 longest = i;
192 longestSq = sq;
193 }
194 const auto d = ( t[longest] - c ).normalized();
195
196 // project triangle on the line (c, d)
197 Triangle3<T> res;
198 for ( int i = 0; i < 3; ++i )
199 res[i] = c + d * dot( d, t[i] - c );
200 return res;
201}
202
205template <typename T>
206[[nodiscard]] Triangle3<T> triangleWithNormal( const Triangle3<T> & t, const Vector3<T> & n )
207{
208 const auto c = ( t[0] + t[1] + t[2] ) / T(3);
209 Triangle3<T> res;
210 for ( int i = 0; i < 3; ++i )
211 res[i] = t[i] - n * dot( n, t[i] - c );
212
213 if ( dot( n, dirDblArea( res ) ) < 0 ) // projected triangle has inversed normal
214 res = makeDegenerate( res );
215 return res;
216}
217
223template <typename T>
224[[nodiscard]] T dihedralAngleSin( const Vector3<T>& leftNorm, const Vector3<T>& rightNorm, const Vector3<T>& edgeVec )
225{
226 auto edgeDir = edgeVec.normalized();
227 return dot( edgeDir, cross( leftNorm, rightNorm ) );
228}
229
235template <typename T>
236[[nodiscard]] T dihedralAngleCos( const Vector3<T>& leftNorm, const Vector3<T>& rightNorm )
237{
238 return dot( leftNorm, rightNorm );
239}
240
247template <typename T>
248[[nodiscard]] T dihedralAngle( const Vector3<T>& leftNorm, const Vector3<T>& rightNorm, const Vector3<T>& edgeVec )
249{
250 auto sin = dihedralAngleSin( leftNorm, rightNorm, edgeVec );
251 auto cos = dihedralAngleCos( leftNorm, rightNorm );
252 return std::atan2( sin, cos );
253}
254
258template <typename T>
259[[nodiscard]] std::optional<Vector2<T>> posFromTriEdgeLengths( T a, T b, T c )
260{
261 if ( c == 0 )
262 {
263 if ( a == b )
264 return Vector2<T>{ a, 0 };
265 else
266 return {};
267 }
268 const auto aa = sqr( a );
269 const auto y = ( aa - sqr( b ) + sqr( c ) ) / ( 2 * c );
270 const auto yy = sqr( y );
271 if ( yy > aa )
272 return {};
273 const auto x = std::sqrt( aa - yy );
274 return Vector2<T>{ x, y };
275}
276
279template <typename T>
280[[nodiscard]] std::optional<T> quadrangleOtherDiagonal( T a, T b, T c, T a1, T b1 )
281{
282 const auto p = posFromTriEdgeLengths( a, b, c );
283 if ( !p )
284 return {};
285 auto p1 = posFromTriEdgeLengths( a1, b1, c );
286 if ( !p1 )
287 return {};
288 p1->x = -p1->x;
289 //where the other diagonal crosses axis Oy
290 auto y = ( p->x * p1->y - p1->x * p->y ) / ( p->x - p1->x );
291 if ( y < 0 || y > c )
292 return {};
293 return ( *p - *p1 ).length();
294}
295
296} // namespace MR
length
Definition MRObjectDimensionsEnum.h:14
T triangleAspectRatio(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
Definition MRTriMath.h:110
T dihedralAngle(const Vector3< T > &leftNorm, const Vector3< T > &rightNorm, const Vector3< T > &edgeVec)
Definition MRTriMath.h:248
T dihedralAngleSin(const Vector3< T > &leftNorm, const Vector3< T > &rightNorm, const Vector3< T > &edgeVec)
Definition MRTriMath.h:224
T circumcircleDiameterSq(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
Definition MRTriMath.h:16
T dihedralAngleCos(const Vector3< T > &leftNorm, const Vector3< T > &rightNorm)
Definition MRTriMath.h:236
T circumcircleDiameter(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
Definition MRTriMath.h:36
T minTriangleAngleSin(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
Definition MRTriMath.h:90
Definition MRCameraOrientationPlugin.h:7
constexpr T sqr(T x) noexcept
Definition MRMesh/MRMeshFwd.h:613
Vector3< T > circumcircleCenter(const Vector3< T > &a, const Vector3< T > &b)
Computes the center of the the triangle's 0AB circumcircle.
Definition MRTriMath.h:43
std::optional< T > quadrangleOtherDiagonal(T a, T b, T c, T a1, T b1)
Definition MRTriMath.h:280
Triangle3< T > makeDegenerate(const Triangle3< T > &t)
make degenerate triangle (all 3 points on a line) that maximally resembles the input one and has the ...
Definition MRTriMath.h:181
Triangle3< T > triangleWithNormal(const Triangle3< T > &t, const Vector3< T > &n)
Definition MRTriMath.h:206
T dblArea(const Vector3< T > &p, const Vector3< T > &q, const Vector3< T > &r)
computes twice the area of given triangle
Definition MRTriMath.h:153
bool circumballCenters(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c, T radius, Vector3< T > &centerPos, Vector3< T > &centerNeg)
Definition MRTriMath.h:69
Vector3< T > dirDblArea(const Triangle3< T > &t)
computes directed double area of given triangle
Definition MRTriMath.h:125
T minTriangleAngle(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
Definition MRTriMath.h:102
T area(const Vector3< T > &p, const Vector3< T > &q, const Vector3< T > &r)
computes twice the area of given triangle
Definition MRTriMath.h:160
std::optional< Vector2< T > > posFromTriEdgeLengths(T a, T b, T c)
Definition MRTriMath.h:259
T dblAreaSq(const Vector3< T > &p, const Vector3< T > &q, const Vector3< T > &r)
computes the square of double area of given triangle
Definition MRTriMath.h:146
Definition MRVector2.h:18
Definition MRMesh/MRVector3.h:19
Vector3 normalized() const MR_REQUIRES_IF_SUPPORTED(std
Definition MRMesh/MRVector3.h:55
T lengthSq() const
Definition MRMesh/MRVector3.h:46