void NurbsTools::pca (const vector_vec2d &data, Eigen::Vector2d &mean, Eigen::Matrix2d &eigenvectors, Eigen::Vector2d &eigenvalues) { if (data.empty ()) { printf ("[NurbsTools::pca] Error, data is empty\n"); abort (); } mean = computeMean (data); unsigned s = unsigned (data.size ()); Eigen::MatrixXd Q (2, s); for (unsigned i = 0; i < s; i++) Q.col (i) << (data[i] - mean); Eigen::Matrix2d C = Q * Q.transpose (); Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eigensolver (C); if (eigensolver.info () != Success) { printf ("[NurbsTools::pca] Can not find eigenvalues.\n"); abort (); } for (int i = 0; i < 2; ++i) { eigenvalues (i) = eigensolver.eigenvalues () (1 - i); eigenvectors.col (i) = eigensolver.eigenvectors ().col (1 - i); } }
static void diagonalizeInertiaTensor( const Matrix3s& I, Matrix3s& R0, Vector3s& I0 ) { // Inertia tensor should by symmetric assert( ( I - I.transpose() ).lpNorm<Eigen::Infinity>() <= 1.0e-6 ); // Inertia tensor should have positive determinant assert( I.determinant() > 0.0 ); // Compute the eigenvectors and eigenvalues of the input matrix const Eigen::SelfAdjointEigenSolver<Matrix3s> es{ I }; // Check for errors if( es.info() == Eigen::NumericalIssue ) { std::cerr << "Warning, failed to compute eigenvalues of inertia tensor due to Eigen::NumericalIssue" << std::endl; } else if( es.info() == Eigen::NoConvergence ) { std::cerr << "Warning, failed to compute eigenvalues of inertia tensor due to Eigen::NoConvergence" << std::endl; } else if( es.info() == Eigen::InvalidInput ) { std::cerr << "Warning, failed to compute eigenvalues of inertia tensor due to Eigen::InvalidInput" << std::endl; } assert( es.info() == Eigen::Success ); // Save the eigenvectors and eigenvalues I0 = es.eigenvalues(); assert( ( I0.array() > 0.0 ).all() ); assert( I0.x() <= I0.y() ); assert( I0.y() <= I0.z() ); R0 = es.eigenvectors(); assert( fabs( fabs( R0.determinant() ) - 1.0 ) <= 1.0e-6 ); // Ensure that we have an orientation preserving transform if( R0.determinant() < 0.0 ) { R0.col( 0 ) *= -1.0; } }
void NurbsTools::pca (const vector_vec3d &data, ON_3dVector &mean, Eigen::Matrix3d &eigenvectors, Eigen::Vector3d &eigenvalues) { if (data.empty ()) { printf ("[NurbsTools::pca] Error, data is empty\n"); abort (); } mean = computeMean (data); unsigned s = data.size (); ON_Matrix Q(3, s); for (unsigned i = 0; i < s; i++) { Q[0][i] = data[i].x - mean.x; Q[1][i] = data[i].y - mean.y; Q[2][i] = data[i].z - mean.z; } ON_Matrix Qt = Q; Qt.Transpose(); ON_Matrix oC; oC.Multiply(Q,Qt); Eigen::Matrix3d C(3,3); for (unsigned i = 0; i < 3; i++) { for (unsigned j = 0; j < 3; j++) { C(i,j) = oC[i][j]; } } Eigen::SelfAdjointEigenSolver < Eigen::Matrix3d > eigensolver (C); if (eigensolver.info () != Eigen::Success) { printf ("[NurbsTools::pca] Can not find eigenvalues.\n"); abort (); } for (int i = 0; i < 3; ++i) { eigenvalues (i) = eigensolver.eigenvalues () (2 - i); if (i == 2) eigenvectors.col (2) = eigenvectors.col (0).cross (eigenvectors.col (1)); else eigenvectors.col (i) = eigensolver.eigenvectors ().col (2 - i); } }