MeshLib C++ Docs
Loading...
Searching...
No Matches
MRSymMatrix3.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRVector3.h"
4#include "MRMatrix3.h"
5#include "MRConstants.h"
6#include <limits>
7
8namespace MR
9{
12
13
16template <typename T>
18{
19 using ValueType = T;
20
22 T xx = 0, xy = 0, xz = 0, yy = 0, yz = 0, zz = 0;
23
24 constexpr SymMatrix3() noexcept = default;
25
28 template <typename U> MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, U> )
29 constexpr explicit SymMatrix3( const SymMatrix3<U> & m ) : xx( T( m.xx ) ), xy( T( m.xy ) ), xz( T( m.xz ) ), yy( T( m.yy ) ), yz( T( m.yz ) ), zz( T( m.zz ) ) { }
30
31 static constexpr SymMatrix3 identity() noexcept { SymMatrix3 res; res.xx = res.yy = res.zz = 1; return res; }
32 static constexpr SymMatrix3 diagonal( T diagVal ) noexcept { SymMatrix3 res; res.xx = res.yy = res.zz = diagVal; return res; }
33
35 constexpr T trace() const noexcept { return xx + yy + zz; }
37 constexpr T normSq() const noexcept;
39 constexpr T det() const noexcept;
41 constexpr SymMatrix3<T> inverse() const noexcept { return inverse( det() ); }
43 constexpr SymMatrix3<T> inverse( T det ) const noexcept;
44
45 SymMatrix3 & operator +=( const SymMatrix3<T> & b ) { xx += b.xx; xy += b.xy; xz += b.xz; yy += b.yy; yz += b.yz; zz += b.zz; return * this; }
46 SymMatrix3 & operator -=( const SymMatrix3<T> & b ) { xx -= b.xx; xy -= b.xy; xz -= b.xz; yy -= b.yy; yz -= b.yz; zz -= b.zz; return * this; }
47 SymMatrix3 & operator *=( T b ) { xx *= b; xy *= b; xz *= b; yy *= b; yz *= b; zz *= b; return * this; }
49 {
50 if constexpr ( std::is_integral_v<T> )
51 { xx /= b; xy /= b; xz /= b; yy /= b; yz /= b; zz /= b; return * this; }
52 else
53 return *this *= ( 1 / b );
54 }
55
59 Vector3<T> eigens( Matrix3<T> * eigenvectors = nullptr ) const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> );
61 Vector3<T> eigenvector( T eigenvalue ) const MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> );
62
68 SymMatrix3<T> pseudoinverse( T tol = std::numeric_limits<T>::epsilon(), int * rank = nullptr, Vector3<T> * space = nullptr ) const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> );
69};
70
73
75template <typename T>
76inline Vector3<T> operator *( const SymMatrix3<T> & a, const Vector3<T> & b )
77{
78 return
79 {
80 a.xx * b.x + a.xy * b.y + a.xz * b.z,
81 a.xy * b.x + a.yy * b.y + a.yz * b.z,
82 a.xz * b.x + a.yz * b.y + a.zz * b.z
83 };
84}
85
87template <typename T>
89{
90 SymMatrix3<T> res;
91 res.xx = a.x * a.x;
92 res.xy = a.x * a.y;
93 res.xz = a.x * a.z;
94 res.yy = a.y * a.y;
95 res.yz = a.y * a.z;
96 res.zz = a.z * a.z;
97 return res;
98}
99
101template <typename T>
102inline SymMatrix3<T> outerSquare( T k, const Vector3<T> & a )
103{
104 const auto ka = k * a;
105 SymMatrix3<T> res;
106 res.xx = ka.x * a.x;
107 res.xy = ka.x * a.y;
108 res.xz = ka.x * a.z;
109 res.yy = ka.y * a.y;
110 res.yz = ka.y * a.z;
111 res.zz = ka.z * a.z;
112 return res;
113}
114
118template <typename T>
120{
121 SymMatrix3<T> res = outerSquare( a );
122 const auto d = a.lengthSq();
123 res.xx -= d;
124 res.yy -= d;
125 res.zz -= d;
126 return res;
127}
128
129template <typename T>
130inline bool operator ==( const SymMatrix3<T> & a, const SymMatrix3<T> & b )
131 { return a.xx = b.xx && a.xy = b.xy && a.xz = b.xz && a.yy = b.yy && a.yz = b.yz && a.zz = b.zz; }
132
133template <typename T>
134inline bool operator !=( const SymMatrix3<T> & a, const SymMatrix3<T> & b )
135 { return !( a == b ); }
136
137template <typename T>
138inline SymMatrix3<T> operator +( const SymMatrix3<T> & a, const SymMatrix3<T> & b )
139 { SymMatrix3<T> res{ a }; res += b; return res; }
140
141template <typename T>
142inline SymMatrix3<T> operator -( const SymMatrix3<T> & a, const SymMatrix3<T> & b )
143 { SymMatrix3<T> res{ a }; res -= b; return res; }
144
145template <typename T>
146inline SymMatrix3<T> operator *( T a, const SymMatrix3<T> & b )
147 { SymMatrix3<T> res{ b }; res *= a; return res; }
148
149template <typename T>
150inline SymMatrix3<T> operator *( const SymMatrix3<T> & b, T a )
151 { SymMatrix3<T> res{ b }; res *= a; return res; }
152
153template <typename T>
155 { b /= a; return b; }
156
157template <typename T>
158constexpr T SymMatrix3<T>::det() const noexcept
159{
160 return
161 xx * ( yy * zz - yz * yz )
162 - xy * ( xy * zz - yz * xz )
163 + xz * ( xy * yz - yy * xz );
164}
165
166template <typename T>
167constexpr T SymMatrix3<T>::normSq() const noexcept
168{
169 return sqr( xx ) + sqr( yy ) + sqr( zz ) +
170 2 * ( sqr( xy ) + sqr( xz ) + sqr( yz ) );
171}
172
173template <typename T>
174constexpr SymMatrix3<T> SymMatrix3<T>::inverse( T det ) const noexcept
175{
176 if ( det == 0 )
177 return {};
178 SymMatrix3<T> res;
179 res.xx = ( yy * zz - yz * yz ) / det;
180 res.xy = ( xz * yz - xy * zz ) / det;
181 res.xz = ( xy * yz - xz * yy ) / det;
182 res.yy = ( xx * zz - xz * xz ) / det;
183 res.yz = ( xz * xy - xx * yz ) / det;
184 res.zz = ( xx * yy - xy * xy ) / det;
185 return res;
186}
187
188template <typename T>
189Vector3<T> SymMatrix3<T>::eigens( Matrix3<T> * eigenvectors ) const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> )
190{
192 const auto q = trace() / 3;
193 const auto B = *this - diagonal( q );
194 const auto p2 = B.normSq();
195 const auto p = std::sqrt( p2 / 6 );
196 Vector3<T> eig;
197 if ( p <= std::abs( q ) * std::numeric_limits<T>::epsilon() )
198 {
200 eig = { q, q, q };
201 if ( eigenvectors )
202 *eigenvectors = Matrix3<T>{};
203 return eig;
204 }
205 const auto r = B.det() / ( 2 * p * p * p );
206
209 if ( r <= -1 )
210 {
212 eig[0] = q - 2 * p;
213 eig[1] = eig[2] = q + p;
214 if ( eigenvectors )
215 {
216 const auto x = eigenvector( eig[0] ).normalized();
217 const auto [ y, z ] = x.perpendicular();
218 *eigenvectors = Matrix3<T>::fromRows( x, y, z );
219 }
220 return eig;
221 }
222 if ( r >= 1 )
223 {
225 eig[0] = eig[1] = q - p;
226 eig[2] = q + 2 * p;
227 if ( eigenvectors )
228 {
229 const auto z = eigenvector( eig[2] ).normalized();
230 const auto [ x, y ] = z.perpendicular();
231 *eigenvectors = Matrix3<T>::fromRows( x, y, z );
232 }
233 return eig;
234 }
235 const auto phi = std::acos( r ) / 3;
236 eig[0] = q + 2 * p * cos( phi + T( 2 * PI / 3 ) );
237 eig[2] = q + 2 * p * cos( phi );
238 eig[1] = 3 * q - eig[0] - eig[2];
239 if ( eigenvectors )
240 {
241 const auto x = eigenvector( eig[0] ).normalized();
242 const auto z = eigenvector( eig[2] ).normalized();
243 const auto y = cross( z, x );
244 *eigenvectors = Matrix3<T>::fromRows( x, y, z );
245 }
246 return eig;
247}
248
249template <typename T>
250Vector3<T> SymMatrix3<T>::eigenvector( T eigenvalue ) const MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> )
251{
252 const Vector3<T> row0( xx - eigenvalue, xy, xz );
253 const Vector3<T> row1( xy, yy - eigenvalue, yz );
254 const Vector3<T> row2( xz, yz, zz - eigenvalue );
256 const Vector3<T> crs01 = cross( row0, row1 );
257 const Vector3<T> crs12 = cross( row1, row2 );
258 const Vector3<T> crs20 = cross( row2, row0 );
259 const T lsq01 = crs01.lengthSq();
260 const T lsq12 = crs12.lengthSq();
261 const T lsq20 = crs20.lengthSq();
262 if ( lsq01 > lsq12 )
263 {
264 if ( lsq01 > lsq20 )
265 return crs01;
266 }
267 else if ( lsq12 > lsq20 )
268 return crs12;
269 return crs20;
270}
271
272template <typename T>
273SymMatrix3<T> SymMatrix3<T>::pseudoinverse( T tol, int * rank, Vector3<T> * space ) const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> )
274{
275 SymMatrix3<T> res;
276 Matrix3<T> eigenvectors;
277 const auto eigenvalues = eigens( &eigenvectors );
278 const auto threshold = std::max( std::abs( eigenvalues[0] ), std::abs( eigenvalues[2] ) ) * tol;
279 int myRank = 0;
280 for ( int i = 0; i < 3; ++i )
281 {
282 if ( std::abs( eigenvalues[i] ) <= threshold )
283 continue;
284 res += outerSquare( 1 / eigenvalues[i], eigenvectors[i] );
285 ++myRank;
286 if ( space )
287 {
288 if ( myRank == 1 )
289 *space = eigenvectors[i];
290 else if ( myRank == 2 )
291 *space = cross( *space, eigenvectors[i] );
292 else
293 *space = Vector3<T>{};
294 }
295 }
296 if ( rank )
297 *rank = myRank;
298 return res;
299}
300
302
303}
#define MR_REQUIRES_IF_SUPPORTED(...)
Definition MRMacros.h:34
BitSet operator-(const BitSet &a, const BitSet &b)
Definition MRBitSet.h:457
MRMESH_API bool operator==(const BitSet &a, const BitSet &b)
compare that two bit sets have the same set bits (they can be equal even if sizes are distinct but la...
static constexpr SymMatrix3 identity() noexcept
Definition MRSymMatrix3.h:31
constexpr T det() const noexcept
computes determinant of the matrix
T xy
Definition MRSymMatrix3.h:22
T x
Definition MRVector3.h:39
T ValueType
Definition MRSymMatrix3.h:19
T y
Definition MRVector3.h:39
bool operator!=(const Color &a, const Color &b)
Definition MRColor.h:104
SymMatrix3< T > crossSquare(const Vector3< T > &a)
Definition MRSymMatrix3.h:119
constexpr SymMatrix3() noexcept=default
SymMatrix3< T > outerSquare(const Vector3< T > &a)
x = a * a^T
Definition MRSymMatrix3.h:88
Color operator/(const Color &b, float a)
Definition MRColor.h:129
T yz
Definition MRSymMatrix3.h:22
SymMatrix3 & operator+=(const SymMatrix3< T > &b)
Definition MRSymMatrix3.h:45
constexpr T normSq() const noexcept
computes the squared norm of the matrix, which is equal to the sum of 9 squared elements
T xz
Definition MRSymMatrix3.h:22
T xx
zero matrix by default
Definition MRSymMatrix3.h:22
SymMatrix3 & operator*=(T b)
Definition MRSymMatrix3.h:47
constexpr SymMatrix3< T > inverse(T det) const noexcept
computes inverse matrix given determinant of this
constexpr T trace() const noexcept
computes trace of the matrix
Definition MRSymMatrix3.h:35
SymMatrix3 & operator-=(const SymMatrix3< T > &b)
Definition MRSymMatrix3.h:46
static constexpr SymMatrix3 diagonal(T diagVal) noexcept
Definition MRSymMatrix3.h:32
static constexpr Matrix3 static rotation(const Vector3< T > &axis, T angle) noexcept MR_REQUIRES_IF_SUPPORTED(std constexpr Matrix3 static rotation(const Vector3< T > &from, const Vector3< T > &to) noexcept MR_REQUIRES_IF_SUPPORTED(std constexpr Matrix3 static rotationFromEuler(const Vector3< T > &eulerAngles) noexcept MR_REQUIRES_IF_SUPPORTED(std constexpr Matrix3 static approximateLinearRotationMatrixFromEuler(const Vector3< T > &eulerAngles) noexcept MR_REQUIRES_IF_SUPPORTED(std constexpr Matrix fromRows)(const Vector3< T > &x, const Vector3< T > &y, const Vector3< T > &z) noexcept
creates matrix representing rotation around given axis on given angle
Definition MRMatrix3.h:62
T zz
Definition MRSymMatrix3.h:22
constexpr SymMatrix3< T > inverse() const noexcept
computes inverse matrix
Definition MRSymMatrix3.h:41
T z
Definition MRVector3.h:39
T yy
Definition MRSymMatrix3.h:22
T lengthSq() const
Definition MRVector3.h:68
SymMatrix3< T > outerSquare(T k, const Vector3< T > &a)
x = k * a * a^T
Definition MRSymMatrix3.h:102
Color operator+(const Color &a, const Color &b)
Definition MRColor.h:109
SymMatrix3 & operator/=(T b)
Definition MRSymMatrix3.h:48
Vector3< T > operator*(const SymMatrix3< T > &a, const Vector3< T > &b)
x = a * b
Definition MRSymMatrix3.h:76
only for bindings generation
Definition MRCameraOrientationPlugin.h:8
Definition MRMatrix3.h:24
Definition MRSymMatrix3.h:18
Definition MRVector3.h:33