MeshLib C++ Docs
Loading...
Searching...
No Matches
MRSymMatrix2.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRVector2.h"
4#include "MRMatrix2.h"
5#include <limits>
6
7namespace MR
8{
9
12template <typename T>
14{
15 using ValueType = T;
16
18 T xx = 0, xy = 0, yy = 0;
19
20 constexpr SymMatrix2() noexcept = default;
21
22 // Here `T == U` doesn't seem to cause any issues in the C++ code, but we're still disabling it because it somehow gets emitted
23 // when generating the bindings, and results in duplicate functions in C#.
24 template <typename U> MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, U> )
25 constexpr explicit SymMatrix2( const SymMatrix2<U> & m ) : xx( T( m.xx ) ), xy( T( m.xy ) ), yy( T( m.yy ) ) { }
26
27 static constexpr SymMatrix2 identity() noexcept { SymMatrix2 res; res.xx = res.yy = 1; return res; }
28 static constexpr SymMatrix2 diagonal( T diagVal ) noexcept { SymMatrix2 res; res.xx = res.yy = diagVal; return res; }
29
31 constexpr T trace() const noexcept { return xx + yy; }
33 constexpr T normSq() const noexcept { return sqr( xx ) + 2 * sqr( xy ) + sqr( yy ); }
35 constexpr T det() const noexcept;
37 constexpr SymMatrix2<T> inverse() const noexcept { return inverse( det() ); }
39 constexpr SymMatrix2<T> inverse( T det ) const noexcept;
40
41 SymMatrix2 & operator +=( const SymMatrix2<T> & b ) { xx += b.xx; xy += b.xy; yy += b.yy; return * this; }
42 SymMatrix2 & operator -=( const SymMatrix2<T> & b ) { xx -= b.xx; xy -= b.xy; yy -= b.yy; return * this; }
43 SymMatrix2 & operator *=( T b ) { xx *= b; xy *= b; yy *= b; return * this; }
45 {
46 if constexpr ( std::is_integral_v<T> )
47 { xx /= b; xy /= b; yy /= b; return * this; }
48 else
49 return *this *= ( 1 / b );
50 }
51
55 Vector2<T> eigens( Matrix2<T> * eigenvectors = nullptr ) const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> );
57 Vector2<T> eigenvector( T eigenvalue ) const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> );
59 Vector2<T> maxEigenvector() const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> );
60
66 SymMatrix2<T> pseudoinverse( T tol = std::numeric_limits<T>::epsilon(), int * rank = nullptr, Vector2<T> * space = nullptr ) const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> );
67};
68
71
73template <typename T>
74inline Vector2<T> operator *( const SymMatrix2<T> & a, const Vector2<T> & b )
75{
76 return
77 {
78 a.xx * b.x + a.xy * b.y,
79 a.xy * b.x + a.yy * b.y
80 };
81}
82
84template <typename T>
86{
87 SymMatrix2<T> res;
88 res.xx = a.x * a.x;
89 res.xy = a.x * a.y;
90 res.yy = a.y * a.y;
91 return res;
92}
93
95template <typename T>
96inline SymMatrix2<T> outerSquare( T k, const Vector2<T> & a )
97{
98 const auto ka = k * a;
99 SymMatrix2<T> res;
100 res.xx = ka.x * a.x;
101 res.xy = ka.x * a.y;
102 res.yy = ka.y * a.y;
103 return res;
104}
105
106template <typename T>
107inline bool operator ==( const SymMatrix2<T> & a, const SymMatrix2<T> & b )
108 { return a.xx = b.xx && a.xy = b.xy && a.yy = b.yy; }
109
110template <typename T>
111inline bool operator !=( const SymMatrix2<T> & a, const SymMatrix2<T> & b )
112 { return !( a == b ); }
113
114template <typename T>
115inline SymMatrix2<T> operator +( const SymMatrix2<T> & a, const SymMatrix2<T> & b )
116 { SymMatrix2<T> res{ a }; res += b; return res; }
117
118template <typename T>
119inline SymMatrix2<T> operator -( const SymMatrix2<T> & a, const SymMatrix2<T> & b )
120 { SymMatrix2<T> res{ a }; res -= b; return res; }
121
122template <typename T>
123inline SymMatrix2<T> operator *( T a, const SymMatrix2<T> & b )
124 { SymMatrix2<T> res{ b }; res *= a; return res; }
125
126template <typename T>
127inline SymMatrix2<T> operator *( const SymMatrix2<T> & b, T a )
128 { SymMatrix2<T> res{ b }; res *= a; return res; }
129
130template <typename T>
132 { b /= a; return b; }
133
134template <typename T>
135constexpr T SymMatrix2<T>::det() const noexcept
136{
137 return xx * yy - xy * xy;
138}
139
140template <typename T>
141constexpr SymMatrix2<T> SymMatrix2<T>::inverse( T det ) const noexcept
142{
143 if ( det == 0 )
144 return {};
145 SymMatrix2<T> res;
146 res.xx = yy / det;
147 res.xy = -xy / det;
148 res.yy = xx / det;
149 return res;
150}
151
152template <typename T>
153Vector2<T> SymMatrix2<T>::eigens( Matrix2<T> * eigenvectors ) const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> )
154{
155 //https://en.wikipedia.org/wiki/Eigenvalue_algorithm#2%C3%972_matrices
156 const auto tr = trace();
157 const auto q = tr / 2;
158 const auto p = std::sqrt( std::max( T(0), sqr( tr ) - 4 * det() ) ) / 2;
159 Vector2<T> eig;
160 if ( p <= std::abs( q ) * std::numeric_limits<T>::epsilon() )
161 {
162 // this is proportional to identity matrix
163 eig = { q, q };
164 if ( eigenvectors )
165 *eigenvectors = Matrix2<T>{};
166 return eig;
167 }
168 eig[0] = q - p;
169 eig[1] = q + p;
170 if ( eigenvectors )
171 {
172 const auto x = eigenvector( eig[0] ).normalized();
173 *eigenvectors = Matrix2<T>::fromRows( x, x.perpendicular() );
174 }
175 return eig;
176}
177
178template <typename T>
179Vector2<T> SymMatrix2<T>::eigenvector( T eigenvalue ) const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> )
180{
181 const Vector2<T> row0( xx - eigenvalue, xy );
182 const Vector2<T> row1( xy, yy - eigenvalue );
183 // not-repeating eigenvalue means that one of two rows is not zero
184 const T lsq0 = row0.lengthSq();
185 const T lsq1 = row1.lengthSq();
186 return lsq0 >= lsq1 ? row0.perpendicular() : row1.perpendicular();
187}
188
189template <typename T>
190Vector2<T> SymMatrix2<T>::maxEigenvector() const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> )
191{
192 const auto tr = trace();
193 const auto q = tr / 2;
194 const auto p = std::sqrt( std::max( T(0), sqr( tr ) - 4 * det() ) ) / 2;
195 if ( p <= std::abs( q ) * std::numeric_limits<T>::epsilon() )
196 {
197 // this is proportional to identity matrix
198 return Vector2<T>( T(1), T(0) );
199 }
200 return eigenvector( q + p );
201}
202
203template <typename T>
204SymMatrix2<T> SymMatrix2<T>::pseudoinverse( T tol, int * rank, Vector2<T> * space ) const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> )
205{
206 SymMatrix2<T> res;
207 Matrix2<T> eigenvectors;
208 const auto eigenvalues = eigens( &eigenvectors );
209 const auto threshold = std::max( std::abs( eigenvalues[0] ), std::abs( eigenvalues[1] ) ) * tol;
210 int myRank = 0;
211 for ( int i = 0; i < 2; ++i )
212 {
213 if ( std::abs( eigenvalues[i] ) <= threshold )
214 continue;
215 res += outerSquare( 1 / eigenvalues[i], eigenvectors[i] );
216 ++myRank;
217 if ( space )
218 {
219 if ( myRank == 1 )
220 *space = eigenvectors[i];
221 else
222 *space = Vector2<T>{};
223 }
224 }
225 if ( rank )
226 *rank = myRank;
227 return res;
228}
229
231
232} // namespace MR
#define MR_REQUIRES_IF_SUPPORTED(...)
Definition MRMacros.h:34
BitSet operator-(const BitSet &a, const BitSet &b)
Definition MRMesh/MRBitSet.h:442
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...
Definition MRCameraOrientationPlugin.h:8
constexpr T sqr(T x) noexcept
squared value
Definition MRMeshFwd.h:752
bool operator!=(const Color &a, const Color &b)
Definition MRMesh/MRColor.h:101
Color operator/(const Color &b, float a)
Definition MRMesh/MRColor.h:126
Color operator+(const Color &a, const Color &b)
Definition MRMesh/MRColor.h:106
Definition MRMatrix2.h:21
static constexpr Matrix2 static rotation(T angle) noexcept MR_REQUIRES_IF_SUPPORTED(std constexpr Matrix2 static rotation(const Vector2< T > &from, const Vector2< T > &to) noexcept MR_REQUIRES_IF_SUPPORTED(std constexpr Matrix fromRows)(const Vector2< T > &x, const Vector2< T > &y) noexcept
creates matrix representing rotation around origin on given angle
Definition MRMatrix2.h:49
Definition MRSymMatrix2.h:14
SymMatrix2 & operator-=(const SymMatrix2< T > &b)
Definition MRSymMatrix2.h:42
constexpr SymMatrix2() noexcept=default
constexpr SymMatrix2< T > inverse() const noexcept
computes inverse matrix
Definition MRSymMatrix2.h:37
T ValueType
Definition MRSymMatrix2.h:15
constexpr T trace() const noexcept
computes trace of the matrix
Definition MRSymMatrix2.h:31
T xy
Definition MRSymMatrix2.h:18
static constexpr SymMatrix2 diagonal(T diagVal) noexcept
Definition MRSymMatrix2.h:28
T yy
Definition MRSymMatrix2.h:18
static constexpr SymMatrix2 identity() noexcept
Definition MRSymMatrix2.h:27
constexpr SymMatrix2< T > inverse(T det) const noexcept
computes inverse matrix given determinant of this
SymMatrix2 & operator*=(T b)
Definition MRSymMatrix2.h:43
SymMatrix2< T > outerSquare(T k, const Vector2< T > &a)
x = k * a * a^T
Definition MRSymMatrix2.h:96
SymMatrix2< T > outerSquare(const Vector2< T > &a)
x = a * a^T
Definition MRSymMatrix2.h:85
Vector2< T > operator*(const SymMatrix2< T > &a, const Vector2< T > &b)
x = a * b
Definition MRSymMatrix2.h:74
SymMatrix2 & operator/=(T b)
Definition MRSymMatrix2.h:44
constexpr T det() const noexcept
computes determinant of the matrix
SymMatrix2 & operator+=(const SymMatrix2< T > &b)
Definition MRSymMatrix2.h:41
constexpr T normSq() const noexcept
computes the squared norm of the matrix, which is equal to the sum of 4 squared elements
Definition MRSymMatrix2.h:33
T xx
zero matrix by default
Definition MRSymMatrix2.h:18
Definition MRVector2.h:29
T x
Definition MRVector2.h:35
T y
Definition MRVector2.h:35