13 template <
typename MatrixType>
24 AutoFlipSVD(
const MatrixType &mtr,
unsigned int computationOptions = 0)
26 compute(mtr, computationOptions);
30 template <
int dim = MatrixType::RowsAtCompileTime>
31 typename std::enable_if<dim == 3, AutoFlipSVD<MatrixType>>::type &
32 compute(
const MatrixType &mtr,
unsigned int computationOptions)
41 if ((computationOptions & Eigen::ComputeFullU) || (computationOptions & Eigen::ComputeFullV))
52 template <
int dim = MatrixType::RowsAtCompileTime>
53 typename std::enable_if<dim == 2, AutoFlipSVD<MatrixType>>::type &
54 compute(
const MatrixType &mtr,
unsigned int computationOptions)
64 Eigen::JacobiSVD<MatrixType>::compute(mtr, computationOptions);
65 flip2d(mtr, computationOptions);
70 void set(
const Eigen::Matrix3d &U,
const Eigen::Vector3d &Sigma,
const Eigen::Matrix3d &
V)
79 void flip2d(
const MatrixType &mtr,
unsigned int computationOptions)
82 bool fullUComputed = (computationOptions & Eigen::ComputeFullU);
83 bool fullVComputed = (computationOptions & Eigen::ComputeFullV);
84 if (fullUComputed && fullVComputed)
86 if (Eigen::JacobiSVD<MatrixType>::m_matrixU.
determinant() < 0.0)
99 if (Eigen::JacobiSVD<MatrixType>::m_matrixV.
determinant() < 0.0)
113 else if (mtr.determinant() < 0.0)
125 if (fullUComputed && fullVComputed)
137 Eigen::Matrix<double, dim, dim> &A)
149 A(0, 0) =
F(1, 1) *
F(2, 2) -
F(1, 2) *
F(2, 1);
150 A(0, 1) =
F(1, 2) *
F(2, 0) -
F(1, 0) *
F(2, 2);
151 A(0, 2) =
F(1, 0) *
F(2, 1) -
F(1, 1) *
F(2, 0);
152 A(1, 0) =
F(0, 2) *
F(2, 1) -
F(0, 1) *
F(2, 2);
153 A(1, 1) =
F(0, 0) *
F(2, 2) -
F(0, 2) *
F(2, 0);
154 A(1, 2) =
F(0, 1) *
F(2, 0) -
F(0, 0) *
F(2, 1);
155 A(2, 0) =
F(0, 1) *
F(1, 2) -
F(0, 2) *
F(1, 1);
156 A(2, 1) =
F(0, 2) *
F(1, 0) -
F(0, 0) *
F(1, 2);
157 A(2, 2) =
F(0, 0) *
F(1, 1) -
F(0, 1) *
F(1, 0);
161 assert(0 &&
"dim not 2 or 3");
166 Eigen::Vector3d &lambda)
172 T m = ((T)1 / 3) * (A_Sym(0, 0) + A_Sym(1, 1) + A_Sym(2, 2));
173 T a00 = A_Sym(0, 0) - m;
174 T a11 = A_Sym(1, 1) - m;
175 T a22 = A_Sym(2, 2) - m;
176 T a12_sqr = A_Sym(0, 1) * A_Sym(0, 1);
177 T a13_sqr = A_Sym(0, 2) * A_Sym(0, 2);
178 T a23_sqr = A_Sym(1, 2) * A_Sym(1, 2);
179 T p = ((T)1 / 6) * (a00 * a00 + a11 * a11 + a22 * a22 + 2 * (a12_sqr + a13_sqr + a23_sqr));
180 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);
182 T disc = p * p * p - q * q;
183 T phi = ((T)1 / 3) * atan2(sqrt(max((T)0, disc)), q);
184 T c = cos(phi), s = sin(phi);
185 T sqrt_p_cos = sqrt_p * c;
186 T root_three_sqrt_p_sin = sqrt((T)3) * sqrt_p * s;
187 lambda(0) = m + 2 * sqrt_p_cos;
188 lambda(1) = m - sqrt_p_cos - root_three_sqrt_p_sin;
189 lambda(2) = m - sqrt_p_cos + root_three_sqrt_p_sin;
190 if (lambda(0) < lambda(1))
191 swap(lambda(0), lambda(1));
192 if (lambda(1) < lambda(2))
193 swap(lambda(1), lambda(2));
194 if (lambda(0) < lambda(1))
195 swap(lambda(0), lambda(1));
198 const Eigen::Vector3d &lambda,
206 bool flipped =
false;
207 Eigen::Vector3d lambda_flip(lambda);
208 if (lambda(0) - lambda(1) < lambda(1) - lambda(2))
210 swap(lambda_flip(0), lambda_flip(2));
216 computeCofactorMtr<3>(A_Sym - lambda_flip(0) * Eigen::Matrix3d::Identity(), C1);
217 Eigen::Matrix3d::Index i;
218 T norm2 = C1.colwise().squaredNorm().maxCoeff(&i);
222 T one_over_sqrt = (T)1 / sqrt(norm2);
223 v1 = C1.col(i) * one_over_sqrt;
229 Eigen::Vector3d v1_orthogonal = v1.unitOrthogonal();
230 Eigen::Matrix<T, 3, 2> other_v;
231 other_v.col(0) = v1_orthogonal;
232 other_v.col(1) = v1.cross(v1_orthogonal);
233 Eigen::Matrix2d A_reduced = other_v.transpose() * A_Sym * other_v;
237 computeCofactorMtr<2>(A_reduced - lambda_flip(2) * Eigen::Matrix2d::Identity(), C3);
238 Eigen::Matrix2d::Index j;
239 norm2 = C3.colwise().squaredNorm().maxCoeff(&j);
243 T one_over_sqrt = (T)1 / sqrt(norm2);
244 v3 = other_v * C3.col(j) * one_over_sqrt;
249 Eigen::Vector3d v2 = v3.cross(v1);
266 Eigen::Vector3d &lambda,
282 Eigen::Vector3d lambda;
287 lambda = (lambda.array() >= (T)0).select(lambda, (T)0);
289 if (A.determinant() < 0)
293 U.col(0) = A *
V.col(0);
294 T norm = U.col(0).norm();
297 T one_over_norm = (T)1 / norm;
298 U.col(0) = U.col(0) * one_over_norm;
302 Eigen::Vector3d v1_orthogonal = U.col(0).unitOrthogonal();
303 Eigen::Matrix<T, 3, 2> other_v;
304 other_v.col(0) = v1_orthogonal;
305 other_v.col(1) = U.col(0).cross(v1_orthogonal);
306 Eigen::Vector2d w = other_v.transpose() * A *
V.col(1);
310 T one_over_norm = (T)1 / norm;
311 w = w * one_over_norm;
315 U.col(1) = other_v * w;
316 U.col(2) = U.col(0).cross(U.col(1));
324 Eigen::Vector3d lambda;
329 lambda = (lambda.array() >= (T)0).select(lambda, (T)0);
331 if (A.determinant() < 0)
336 const typename Eigen::JacobiSVD<MatrixType>::SingularValuesType &
singularValues(
void)
const
344 return Eigen::JacobiSVD<MatrixType>::singularValues();
355 return Eigen::JacobiSVD<MatrixType>::matrixU();
366 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)