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); } }
ON_NurbsCurve FittingCurve2d::initCPsNurbsCurve2D (int order, const vector_vec2d &cps) { int cp_red = order - 2; ON_NurbsCurve nurbs; if (cps.size () < 3 || cps.size () < (2 * cp_red + 1)) { printf ("[FittingCurve2d::initCPsNurbsCurve2D] Warning, number of control points too low.\n"); return nurbs; } int ncps = cps.size () + 2 * cp_red; // +2*cp_red for smoothness and +1 for closing nurbs = ON_NurbsCurve (2, false, order, ncps); nurbs.MakePeriodicUniformKnotVector (1.0 / (ncps - order + 1)); for (int j = 0; j < cps.size (); j++) nurbs.SetCV (cp_red + j, ON_3dPoint (cps[j] (0), cps[j] (1), 0.0)); // close nurbs nurbs.SetCV (cp_red + cps.size (), ON_3dPoint (cps[0] (0), cps[0] (1), 0.0)); // make smooth at closing point for (int j = 0; j < cp_red; j++) { ON_3dPoint cp; nurbs.GetCV (nurbs.CVCount () - 1 - cp_red + j, cp); nurbs.SetCV (j, cp); nurbs.GetCV (cp_red - j, cp); nurbs.SetCV (nurbs.CVCount () - 1 - j, cp); } return nurbs; }
ON_NurbsCurve FittingCurve2d::initCPsNurbsCurve2D (int order, const vector_vec2d &cps) { ON_NurbsCurve nurbs; if ((int)cps.size () < (2 * order)) { printf ("[FittingCurve2d::initCPsNurbsCurve2D] Warning, number of control points too low.\n"); return nurbs; } int cp_red = order - 2; int ncps = cps.size () + cp_red; nurbs = ON_NurbsCurve (2, false, order, ncps); nurbs.MakePeriodicUniformKnotVector (1.0 / (ncps - order + 1)); for (int j = 0; j < ncps; j++) nurbs.SetCV (j, ON_3dPoint (cps[j] (0), cps[j] (1), 0.0)); for (int j = 0; j < cp_red; j++) { ON_3dPoint cp; nurbs.GetCV (nurbs.m_cv_count - 1 - cp_red + j, cp); nurbs.SetCV (j, cp); nurbs.GetCV (cp_red - j, cp); nurbs.SetCV (nurbs.m_cv_count - 1 - j, cp); } return nurbs; }
void ClosingBoundary::sampleFromBoundary (ON_NurbsSurface *nurbs, vector_vec3d &point_list, vector_vec2d ¶m_list, unsigned samples) { double ds = 1.0 / (samples - 1); double minU = nurbs->Knot (0, 0); double maxU = nurbs->Knot (0, nurbs->KnotCount (0) - 1); double minV = nurbs->Knot (1, 0); double maxV = nurbs->Knot (1, nurbs->KnotCount (1) - 1); Eigen::Vector2d params; Eigen::Vector3d point; double points[3]; // WEST params (0) = minU; for (unsigned i = 0; i < samples; i++) { params (1) = minV + (maxV - minV) * ds * i; nurbs->Evaluate (params (0), params (1), 0, 3, points); point_list.push_back (Eigen::Vector3d (points[0], points[1], points[2])); param_list.push_back (params); } // EAST params (0) = maxU; for (unsigned i = 0; i < samples; i++) { params (1) = minV + (maxV - minV) * ds * i; nurbs->Evaluate (params (0), params (1), 0, 3, points); point_list.push_back (Eigen::Vector3d (points[0], points[1], points[2])); param_list.push_back (params); } // SOUTH params (1) = minV; for (unsigned i = 0; i < samples; i++) { params (0) = minU + (maxU - minU) * ds * i; nurbs->Evaluate (params (0), params (1), 0, 3, points); point_list.push_back (Eigen::Vector3d (points[0], points[1], points[2])); param_list.push_back (params); } // NORTH params (1) = maxV; for (unsigned i = 0; i < samples; i++) { params (0) = minU + (maxU - minU) * ds * i; nurbs->Evaluate (params (0), params (1), 0, 3, points); point_list.push_back (Eigen::Vector3d (points[0], points[1], points[2])); param_list.push_back (params); } }
unsigned NurbsTools::getClosestPoint (const Eigen::Vector2d &p, const vector_vec2d &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_2dPoint &p, const vector_vec2d &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_2dVector v = (data[i] - p); double d2 = ON_DotProduct(v, v); // Was the squaredNorm in Eigen if (d2 < dist2) { idx = i; dist2 = d2; } } return idx; }
ON_2dVector NurbsTools::computeMean (const vector_vec2d &data) { ON_2dVector u (0.0, 0.0); unsigned s = data.size (); double ds = 1.0 / s; for (unsigned i = 0; i < s; i++) u += (data[i] * ds); return u; }
Eigen::Vector2d NurbsTools::computeMean (const vector_vec2d &data) { Eigen::Vector2d u (0.0, 0.0); size_t s = data.size (); double ds = 1.0 / double (s); for (size_t i = 0; i < s; i++) u += (data[i] * ds); return u; }
ON_NurbsCurve FittingCurve2d::initNurbsCurve2D (int order, const vector_vec2d &data, int ncps, double radiusF) { if (data.empty ()) printf ("[FittingCurve2d::initNurbsCurve2D] Warning, no boundary parameters available\n"); Eigen::Vector2d mean = NurbsTools::computeMean (data); unsigned s = data.size (); double r (0.0); for (unsigned i = 0; i < s; i++) { Eigen::Vector2d d = data[i] - mean; double sn = d.squaredNorm (); if (sn > r) r = sn; } r = radiusF * sqrt (r); if (ncps < 2 * order) ncps = 2 * order; ON_NurbsCurve nurbs = ON_NurbsCurve (2, false, order, ncps); nurbs.MakePeriodicUniformKnotVector (1.0 / (ncps - order + 1)); double dcv = (2.0 * M_PI) / (ncps - order + 1); Eigen::Vector2d cv; for (int j = 0; j < ncps; j++) { cv (0) = r * sin (dcv * j); cv (1) = r * cos (dcv * j); cv = cv + mean; nurbs.SetCV (j, ON_3dPoint (cv (0), cv (1), 0.0)); } return nurbs; }
unsigned NurbsTools::getClosestPoint (const ON_2dPoint &p, const ON_2dVector &dir, const vector_vec2d &data, unsigned &idxcp) { if (data.empty ()) throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data empty.\n"); unsigned idx (0); idxcp = 0; double dist2 (0.0); double dist2cp (DBL_MAX); for (unsigned i = 0; i < data.size (); i++) { ON_2dVector v = (data[i] - p); double d2 = ON_DotProduct(v, v); if (d2 < dist2cp) { idxcp = i; dist2cp = d2; } if (NEAR_ZERO(d2, SMALL_FASTF)) return i; v.Unitize(); double d1 = ON_DotProduct(dir, v); if (d1 / d2 > dist2) { idx = i; dist2 = d1 / d2; } } return idx; }
unsigned NurbsTools::getClosestPoint (const Eigen::Vector2d &p, const Eigen::Vector2d &dir, const vector_vec2d &data, unsigned &idxcp) { if (data.empty ()) throw std::runtime_error ("[NurbsTools::getClosestPoint(2d)] Data empty.\n"); size_t idx = 0; idxcp = 0; double dist2 (0.0); double dist2cp (DBL_MAX); for (size_t i = 0; i < data.size (); i++) { Eigen::Vector2d v = (data[i] - p); double d2 = v.squaredNorm (); if (d2 < dist2cp) { idxcp = i; dist2cp = d2; } if (d2 == 0.0) return i; v.normalize (); double d1 = dir.dot (v); if (d1 / d2 > dist2) { idx = i; dist2 = d1 / d2; } } return idx; }
Eigen::Vector2d NurbsTools::computeVariance (const Eigen::Vector2d &mean, const vector_vec2d &data) { Eigen::Vector2d var (0.0, 0.0); size_t s = data.size (); double ds = 1.0 / double (s); for (size_t i = 0; i < s; i++) { Eigen::Vector2d v = data[i] - mean; var += Eigen::Vector2d (v (0) * v (0) * ds, v (1) * v (1) * ds); } return var; }