void GlobalOptimization::setCommonBoundary (const vector_vec3d &boundary, const vector_vec2i &nurbs_indices) { if (boundary.empty () || boundary.size () != nurbs_indices.size ()) { printf ("[GlobalOptimization::setCommonBoundary] Error, common boundary empty or size does not match.\n"); return; } }
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); } }
unsigned NurbsTools::getClosestPoint (const Eigen::Vector3d &p, const vector_vec3d &data) { if (data.empty ()) throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data empty.\n"); size_t idx = 0; double dist2 (DBL_MAX); for (size_t i = 0; i < data.size (); i++) { double d2 = (data[i] - p).squaredNorm (); if (d2 < dist2) { idx = i; dist2 = d2; } } return idx; }
unsigned NurbsTools::getClosestPoint (const ON_3dPoint &p, const vector_vec3d &data) { if (data.empty ()) throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data empty.\n"); unsigned idx (0); double dist2 (DBL_MAX); for (unsigned i = 0; i < data.size (); i++) { ON_3dVector v = (data[i] - p); double d2 = ON_DotProduct(v, v); // Was the squaredNorm in Eigen if (d2 < dist2) { idx = i; dist2 = d2; } } return idx; }
void NurbsTools::pca (const vector_vec3d &data, Eigen::Vector3d &mean, Eigen::Matrix3d &eigenvectors, Eigen::Vector3d &eigenvalues) { if (data.empty ()) { printf ("[NurbsTools::pca] Error, data is empty\n"); abort (); } mean = computeMean (data); unsigned s = unsigned (data.size ()); Eigen::MatrixXd Q (3, s); for (unsigned i = 0; i < s; i++) Q.col (i) << (data[i] - mean); Eigen::Matrix3d C = Q * Q.transpose (); Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eigensolver (C); if (eigensolver.info () != 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); } }
ON_NurbsCurve FittingCurve::initNurbsCurvePCA (int order, const vector_vec3d &data, int ncps, double rf) { if (data.empty ()) printf ("[FittingCurve::initNurbsCurvePCA] Warning, no boundary parameters available\n"); Eigen::Vector3d mean; Eigen::Matrix3d eigenvectors; Eigen::Vector3d eigenvalues; unsigned s = unsigned (data.size ()); NurbsTools::pca (data, mean, eigenvectors, eigenvalues); eigenvalues = eigenvalues / s; // seems that the eigenvalues are dependent on the number of points (???) double r = rf * sqrt (eigenvalues (0)); if (ncps < 2 * order) ncps = 2 * order; ON_NurbsCurve nurbs = ON_NurbsCurve (3, false, order, ncps); nurbs.MakePeriodicUniformKnotVector (1.0 / (ncps - order + 1)); double dcv = (2.0 * M_PI) / (ncps - order + 1); Eigen::Vector3d cv, cv_t; for (int j = 0; j < ncps; j++) { cv (0) = r * sin (dcv * j); cv (1) = r * cos (dcv * j); cv (2) = 0.0; cv_t = eigenvectors * cv + mean; nurbs.SetCV (j, ON_3dPoint (cv_t (0), cv_t (1), cv_t (2))); } return nurbs; }