13 template <
typename MatrixType>
23 AutoFlipSVD(
const MatrixType& mtr,
unsigned int computationOptions = 0)
25 compute(mtr, computationOptions);
29 template <
int dim = MatrixType::RowsAtCompileTime>
30 typename std::enable_if<dim == 3, AutoFlipSVD<MatrixType>>::type&
31 compute(
const MatrixType& mtr,
unsigned int computationOptions)
40 if ((computationOptions & Eigen::ComputeFullU) || (computationOptions & Eigen::ComputeFullV)) {
49 template <
int dim = MatrixType::RowsAtCompileTime>
50 typename std::enable_if<dim == 2, AutoFlipSVD<MatrixType>>::type&
51 compute(
const MatrixType& mtr,
unsigned int computationOptions)
61 Eigen::JacobiSVD<MatrixType>::compute(mtr, computationOptions);
62 flip2d(mtr, computationOptions);
67 void set(
const Eigen::Matrix3d& U,
const Eigen::Vector3d& Sigma,
const Eigen::Matrix3d&
V)
76 void flip2d(
const MatrixType& mtr,
unsigned int computationOptions)
79 bool fullUComputed = (computationOptions & Eigen::ComputeFullU);
80 bool fullVComputed = (computationOptions & Eigen::ComputeFullV);
81 if (fullUComputed && fullVComputed) {
82 if (Eigen::JacobiSVD<MatrixType>::m_matrixU.
determinant() < 0.0) {
93 if (Eigen::JacobiSVD<MatrixType>::m_matrixV.
determinant() < 0.0) {
105 else if (mtr.determinant() < 0.0) {
115 if (fullUComputed && fullVComputed) {
126 Eigen::Matrix<double, dim, dim>& A)
137 A(0, 0) =
F(1, 1) *
F(2, 2) -
F(1, 2) *
F(2, 1);
138 A(0, 1) =
F(1, 2) *
F(2, 0) -
F(1, 0) *
F(2, 2);
139 A(0, 2) =
F(1, 0) *
F(2, 1) -
F(1, 1) *
F(2, 0);
140 A(1, 0) =
F(0, 2) *
F(2, 1) -
F(0, 1) *
F(2, 2);
141 A(1, 1) =
F(0, 0) *
F(2, 2) -
F(0, 2) *
F(2, 0);
142 A(1, 2) =
F(0, 1) *
F(2, 0) -
F(0, 0) *
F(2, 1);
143 A(2, 0) =
F(0, 1) *
F(1, 2) -
F(0, 2) *
F(1, 1);
144 A(2, 1) =
F(0, 2) *
F(1, 0) -
F(0, 0) *
F(1, 2);
145 A(2, 2) =
F(0, 0) *
F(1, 1) -
F(0, 1) *
F(1, 0);
149 assert(0 &&
"dim not 2 or 3");
154 Eigen::Vector3d& lambda)
160 T m = ((T)1 / 3) * (A_Sym(0, 0) + A_Sym(1, 1) + A_Sym(2, 2));
161 T a00 = A_Sym(0, 0) - m;
162 T a11 = A_Sym(1, 1) - m;
163 T a22 = A_Sym(2, 2) - m;
164 T a12_sqr = A_Sym(0, 1) * A_Sym(0, 1);
165 T a13_sqr = A_Sym(0, 2) * A_Sym(0, 2);
166 T a23_sqr = A_Sym(1, 2) * A_Sym(1, 2);
167 T p = ((T)1 / 6) * (a00 * a00 + a11 * a11 + a22 * a22 + 2 * (a12_sqr + a13_sqr + a23_sqr));
168 T q = (T).5 * (a00 * (a11 * a22 - a23_sqr) - a11 * a13_sqr - a22 * a12_sqr) + A_Sym(0, 1) * A_Sym(0, 2) * A_Sym(1, 2);
170 T disc = p * p * p - q * q;
171 T phi = ((T)1 / 3) * atan2(sqrt(max((T)0, disc)), q);
172 T c = cos(phi), s = sin(phi);
173 T sqrt_p_cos = sqrt_p * c;
174 T root_three_sqrt_p_sin = sqrt((T)3) * sqrt_p * s;
175 lambda(0) = m + 2 * sqrt_p_cos;
176 lambda(1) = m - sqrt_p_cos - root_three_sqrt_p_sin;
177 lambda(2) = m - sqrt_p_cos + root_three_sqrt_p_sin;
178 if (lambda(0) < lambda(1))
179 swap(lambda(0), lambda(1));
180 if (lambda(1) < lambda(2))
181 swap(lambda(1), lambda(2));
182 if (lambda(0) < lambda(1))
183 swap(lambda(0), lambda(1));
186 const Eigen::Vector3d& lambda,
194 bool flipped =
false;
195 Eigen::Vector3d lambda_flip(lambda);
196 if (lambda(0) - lambda(1) < lambda(1) - lambda(2)) {
197 swap(lambda_flip(0), lambda_flip(2));
203 computeCofactorMtr<3>(A_Sym - lambda_flip(0) * Eigen::Matrix3d::Identity(), C1);
204 Eigen::Matrix3d::Index i;
205 T norm2 = C1.colwise().squaredNorm().maxCoeff(&i);
208 T one_over_sqrt = (T)1 / sqrt(norm2);
209 v1 = C1.col(i) * one_over_sqrt;
215 Eigen::Vector3d v1_orthogonal = v1.unitOrthogonal();
216 Eigen::Matrix<T, 3, 2> other_v;
217 other_v.col(0) = v1_orthogonal;
218 other_v.col(1) = v1.cross(v1_orthogonal);
219 Eigen::Matrix2d A_reduced = other_v.transpose() * A_Sym * other_v;
223 computeCofactorMtr<2>(A_reduced - lambda_flip(2) * Eigen::Matrix2d::Identity(), C3);
224 Eigen::Matrix2d::Index j;
225 norm2 = C3.colwise().squaredNorm().maxCoeff(&j);
228 T one_over_sqrt = (T)1 / sqrt(norm2);
229 v3 = other_v * C3.col(j) * one_over_sqrt;
234 Eigen::Vector3d v2 = v3.cross(v1);
249 Eigen::Vector3d& lambda,
265 Eigen::Vector3d lambda;
270 lambda = (lambda.array() >= (T)0).select(lambda, (T)0);
272 if (A.determinant() < 0)
276 U.col(0) = A *
V.col(0);
277 T norm = U.col(0).norm();
279 T one_over_norm = (T)1 / norm;
280 U.col(0) = U.col(0) * one_over_norm;
284 Eigen::Vector3d v1_orthogonal = U.col(0).unitOrthogonal();
285 Eigen::Matrix<T, 3, 2> other_v;
286 other_v.col(0) = v1_orthogonal;
287 other_v.col(1) = U.col(0).cross(v1_orthogonal);
288 Eigen::Vector2d w = other_v.transpose() * A *
V.col(1);
291 T one_over_norm = (T)1 / norm;
292 w = w * one_over_norm;
296 U.col(1) = other_v * w;
297 U.col(2) = U.col(0).cross(U.col(1));
305 Eigen::Vector3d lambda;
310 lambda = (lambda.array() >= (T)0).select(lambda, (T)0);
312 if (A.determinant() < 0)
317 const typename Eigen::JacobiSVD<MatrixType>::SingularValuesType&
singularValues(
void)
const
323 return Eigen::JacobiSVD<MatrixType>::singularValues();
332 return Eigen::JacobiSVD<MatrixType>::matrixU();
341 return Eigen::JacobiSVD<MatrixType>::matrixV();
const Eigen::JacobiSVD< MatrixType >::SingularValuesType & singularValues(void) const
std::enable_if< dim==2, AutoFlipSVD< MatrixType > >::type & compute(const MatrixType &mtr, unsigned int computationOptions)
void fastComputeSingularValues3d(const Eigen::Matrix3d &A, Eigen::Vector3d &singular_values)
void fastSolveEigenproblem(const Eigen::Matrix3d &A_Sym, Eigen::Vector3d &lambda, Eigen::Matrix3d &V)
MatrixType matrixU_flipped
void fastEigenvectors(const Eigen::Matrix3d &A_Sym, const Eigen::Vector3d &lambda, Eigen::Matrix3d &V)
const MatrixType & matrixV(void) const
AutoFlipSVD(const MatrixType &mtr, unsigned int computationOptions=0)
void flip2d(const MatrixType &mtr, unsigned int computationOptions)
void fastSVD3d(const Eigen::Matrix3d &A, Eigen::Matrix3d &U, Eigen::Vector3d &singular_values, Eigen::Matrix3d &V)
void computeCofactorMtr(const Eigen::Matrix< double, dim, dim > &F, Eigen::Matrix< double, dim, dim > &A)
const MatrixType & matrixU(void) const
Eigen::JacobiSVD< MatrixType >::SingularValuesType singularValues_flipped
void fastEigenvalues(const Eigen::Matrix3d &A_Sym, Eigen::Vector3d &lambda)
MatrixType matrixV_flipped
std::enable_if< dim==3, AutoFlipSVD< MatrixType > >::type & compute(const MatrixType &mtr, unsigned int computationOptions)
void set(const Eigen::Matrix3d &U, const Eigen::Vector3d &Sigma, const Eigen::Matrix3d &V)
enable_if_t< isSize< TA >(2, 2) &&isSize< Ts >(2, 1)> singularValueDecomposition(const Eigen::MatrixBase< TA > &A, GivensRotation< T > &U, const Eigen::MatrixBase< Ts > &Sigma, GivensRotation< T > &V, const ScalarType< TA > tol=64 *std::numeric_limits< ScalarType< TA > >::epsilon())
2x2 SVD (singular value decomposition) A=USV'
Eigen::Vector< double, dim > singular_values(const Eigen::Matrix< double, dim, dim > &A)
T determinant(const Eigen::Matrix< T, rows, cols, option, maxRow, maxCol > &mat)