std::vector<double> FittingSurface::getElementVector (const ON_NurbsSurface &nurbs, int dim) // ! { std::vector<double> result; int idx_min = 0; int idx_max = nurbs.KnotCount (dim) - 1; if (nurbs.IsClosed (dim)) { idx_min = nurbs.Order (dim) - 2; idx_max = nurbs.KnotCount (dim) - nurbs.Order (dim) + 1; } const double* knots = nurbs.Knot (dim); result.push_back (knots[idx_min]); //for(int E=(m_nurbs.Order(0)-2); E<(m_nurbs.KnotCount(0)-m_nurbs.Order(0)+2); E++) { for (int E = idx_min + 1; E <= idx_max; E++) { if (!NEAR_EQUAL(knots[E], knots[E - 1], SMALL_FASTF)) // do not count double knots result.push_back (knots[E]); } return result; }
std::vector<double> FittingCylinder::getElementVector (const ON_NurbsSurface &nurbs, int dim) // ! { std::vector<double> result; if (dim == 0) { int idx_min = 0; int idx_max = nurbs.KnotCount (0) - 1; if (nurbs.IsClosed (0)) { idx_min = nurbs.Order (0) - 2; idx_max = nurbs.KnotCount (0) - nurbs.Order (0) + 1; } const double* knotsU = nurbs.Knot (0); result.push_back (knotsU[idx_min]); //for(int E=(m_nurbs.m_order[0]-2); E<(m_nurbs.m_knot_capacity[0]-m_nurbs.m_order[0]+2); E++) { for (int E = idx_min + 1; E <= idx_max; E++) { if (knotsU[E] != knotsU[E - 1]) // do not count double knots result.push_back (knotsU[E]); } } else if (dim == 1) { int idx_min = 0; int idx_max = nurbs.KnotCount (1) - 1; if (nurbs.IsClosed (1)) { idx_min = nurbs.Order (1) - 2; idx_max = nurbs.KnotCount (1) - nurbs.Order (1) + 1; } const double* knotsV = nurbs.Knot (1); result.push_back (knotsV[idx_min]); //for(int F=(m_nurbs.m_order[1]-2); F<(m_nurbs.m_knot_capacity[1]-m_nurbs.m_order[1]+2); F++) { for (int F = idx_min + 1; F <= idx_max; F++) { if (knotsV[F] != knotsV[F - 1]) result.push_back (knotsV[F]); } } else printf ("[FittingCylinder::getElementVector] Error, index exceeds problem dimensions!\n"); return result; }
ON_NurbsSurface FittingSurface::initNurbsPCA (int order, NurbsDataSurface *m_data, ON_3dVector z) { ON_3dVector mean; Eigen::Matrix3d eigenvectors; Eigen::Vector3d eigenvalues; unsigned s = m_data->interior.size (); NurbsTools::pca (m_data->interior, mean, eigenvectors, eigenvalues); m_data->mean = mean; //m_data->eigenvectors = (*eigenvectors); bool flip (false); Eigen::Vector3d ez(z[0],z[1],z[2]); if (eigenvectors.col (2).dot (ez) < 0.0) flip = true; eigenvalues = eigenvalues / s; // seems that the eigenvalues are dependent on the number of points (???) ON_3dVector sigma(sqrt(eigenvalues[0]), sqrt(eigenvalues[1]), sqrt(eigenvalues[2])); ON_NurbsSurface nurbs (3, false, order, order, order, order); nurbs.MakeClampedUniformKnotVector (0, 1.0); nurbs.MakeClampedUniformKnotVector (1, 1.0); // +- 2 sigma -> 95,45 % aller Messwerte double dcu = (4.0 * sigma[0]) / (nurbs.Order (0) - 1); double dcv = (4.0 * sigma[1]) / (nurbs.Order (1) - 1); ON_3dVector cv_t, cv; Eigen::Vector3d ecv_t, ecv; Eigen::Vector3d emean(mean[0], mean[1], mean[2]); for (int i = 0; i < nurbs.Order (0); i++) { for (int j = 0; j < nurbs.Order (1); j++) { cv[0] = -2.0 * sigma[0] + dcu * i; cv[1] = -2.0 * sigma[1] + dcv * j; cv[2] = 0.0; ecv (0) = -2.0 * sigma[0] + dcu * i; ecv (1) = -2.0 * sigma[1] + dcv * j; ecv (2) = 0.0; ecv_t = eigenvectors * ecv + emean; cv_t[0] = ecv_t (0); cv_t[1] = ecv_t (1); cv_t[2] = ecv_t (2); if (flip) nurbs.SetCV (nurbs.Order (0) - 1 - i, j, ON_3dPoint (cv_t[0], cv_t[1], cv_t[2])); else nurbs.SetCV (i, j, ON_3dPoint (cv_t[0], cv_t[1], cv_t[2])); } } return nurbs; }
ON_NurbsSurface FittingSurface::initNurbsPCA (int order, NurbsDataSurface *m_data, Eigen::Vector3d z) { Eigen::Vector3d mean; Eigen::Matrix3d eigenvectors; Eigen::Vector3d eigenvalues; unsigned s = m_data->interior.size (); NurbsTools::pca (m_data->interior, mean, eigenvectors, eigenvalues); m_data->mean = mean; m_data->eigenvectors = eigenvectors; bool flip (false); if (eigenvectors.col (2).dot (z) < 0.0) flip = true; eigenvalues = eigenvalues / s; // seems that the eigenvalues are dependent on the number of points (???) Eigen::Vector3d sigma (sqrt (eigenvalues (0)), sqrt (eigenvalues (1)), sqrt (eigenvalues (2))); ON_NurbsSurface nurbs (3, false, order, order, order, order); nurbs.MakeClampedUniformKnotVector (0, 1.0); nurbs.MakeClampedUniformKnotVector (1, 1.0); // +- 2 sigma -> 95,45 % aller Messwerte double dcu = (4.0 * sigma (0)) / (nurbs.Order (0) - 1); double dcv = (4.0 * sigma (1)) / (nurbs.Order (1) - 1); Eigen::Vector3d cv_t, cv; for (int i = 0; i < nurbs.Order (0); i++) { for (int j = 0; j < nurbs.Order (1); j++) { cv (0) = -2.0 * sigma (0) + dcu * i; cv (1) = -2.0 * sigma (1) + dcv * j; cv (2) = 0.0; cv_t = eigenvectors * cv + mean; if (flip) nurbs.SetCV (nurbs.Order (0) - 1 - i, j, ON_3dPoint (cv_t (0), cv_t (1), cv_t (2))); else nurbs.SetCV (i, j, ON_3dPoint (cv_t (0), cv_t (1), cv_t (2))); } } return nurbs; }
void ON_GL( const ON_NurbsSurface& s, GLUnurbsObj* nobj, // created with gluNewNurbsRenderer ) GLenum type, // = 0 (and type is automatically set) int bPermitKnotScaling, double* knot_scale0, double* knot_scale1 ) { int i, j, k; // The "bPermitScaling" parameters to the ON_GL() call that // fills in the knot vectors is set to false because any // rescaling that is applied to a surface domain must also // be applied to parameter space trimming curve geometry. // GL "s" knots GLint sknot_count = s.KnotCount(0) + 2; GLfloat* sknot = (GLfloat*)onmalloc( sknot_count*sizeof(*sknot) ); ON_GL( s.Order(0), s.CVCount(0), s.Knot(0), sknot, bPermitKnotScaling, knot_scale0 ); // GL "t" knots GLint tknot_count = s.KnotCount(1) + 2; GLfloat* tknot = (GLfloat*)onmalloc( tknot_count*sizeof(*tknot) ); ON_GL( s.Order(1), s.CVCount(1), s.Knot(1), tknot, bPermitKnotScaling, knot_scale1 ); // control vertices const int cv_size= s.CVSize(); const int cv_count[2] = {s.CVCount(0), s.CVCount(1)}; GLint s_stride = cv_size*cv_count[1]; GLint t_stride = cv_size; GLfloat* ctlarray = (GLfloat*)onmalloc( s_stride*cv_count[0]*sizeof(*ctlarray) ); for ( i = 0; i < cv_count[0]; i++ ) { for ( j = 0; j < cv_count[1]; j++ ) { const double* cv = s.CV(i,j); GLfloat* gl_cv = ctlarray + s_stride*i + t_stride*j; for ( k = 0; k < cv_size; k++ ) { gl_cv[k] = (GLfloat)cv[k]; } } } GLint sorder = s.Order(0); GLint torder = s.Order(1); if ( type == 0 ) { // set GL surface type for 3d CVs in homogeneous/euclidean form. type = ( s.IsRational() ) ? GL_MAP2_VERTEX_4 : GL_MAP2_VERTEX_3; } gluNurbsSurface ( nobj, sknot_count, sknot, tknot_count, tknot, s_stride, t_stride, ctlarray, sorder, torder, type ); onfree( ctlarray ); onfree( tknot ); onfree( sknot ); }
ON_NurbsSurface FittingSurface::initNurbsPCABoundingBox (int order, NurbsDataSurface *m_data, ON_3dVector z) { ON_3dVector mean; Eigen::Matrix3d eigenvectors; Eigen::Vector3d eigenvalues; unsigned s = m_data->interior.size (); m_data->interior_param.clear (); NurbsTools::pca (m_data->interior, mean, eigenvectors, eigenvalues); m_data->mean = mean; //m_data->eigenvectors = (*eigenvectors); bool flip (false); Eigen::Vector3d ez(z[0],z[1],z[2]); if (eigenvectors.col (2).dot (ez) < 0.0) flip = true; eigenvalues = eigenvalues / s; // seems that the eigenvalues are dependent on the number of points (???) Eigen::Matrix3d eigenvectors_inv = eigenvectors.inverse (); ON_3dVector v_max(0.0, 0.0, 0.0); ON_3dVector v_min(DBL_MAX, DBL_MAX, DBL_MAX); Eigen::Vector3d emean(mean[0], mean[1], mean[2]); for (unsigned i = 0; i < s; i++) { Eigen::Vector3d eint(m_data->interior[i][0], m_data->interior[i][1], m_data->interior[i][2]); Eigen::Vector3d ep = eigenvectors_inv * (eint - emean); ON_3dPoint p(ep (0), ep (1), ep(2)); m_data->interior_param.push_back (ON_2dPoint(p[0], p[1])); if (p[0] > v_max[0]) v_max[0] = p[0]; if (p[1] > v_max[1]) v_max[1] = p[1]; if (p[2] > v_max[2]) v_max[2] = p[2]; if (p[0] < v_min[0]) v_min[0] = p[0]; if (p[1] < v_min[1]) v_min[1] = p[1]; if (p[2] < v_min[2]) v_min[2] = p[2]; } for (unsigned i = 0; i < s; i++) { ON_2dVector &p = m_data->interior_param[i]; if (v_max[0] > v_min[0] && v_max[0] > v_min[0]) { p[0] = (p[0] - v_min[0]) / (v_max[0] - v_min[0]); p[1] = (p[1] - v_min[1]) / (v_max[1] - v_min[1]); } else { throw std::runtime_error ("[NurbsTools::initNurbsPCABoundingBox] Error: v_max <= v_min"); } } ON_NurbsSurface nurbs (3, false, order, order, order, order); nurbs.MakeClampedUniformKnotVector (0, 1.0); nurbs.MakeClampedUniformKnotVector (1, 1.0); double dcu = (v_max[0] - v_min[0]) / (nurbs.Order (0) - 1); double dcv = (v_max[1] - v_min[1]) / (nurbs.Order (1) - 1); ON_3dPoint cv_t, cv; Eigen::Vector3d ecv_t2, ecv2; Eigen::Vector3d emean2(mean[0],mean[1],mean[2]); for (int i = 0; i < nurbs.Order (0); i++) { for (int j = 0; j < nurbs.Order (1); j++) { cv[0] = v_min[0] + dcu * i; cv[1] = v_min[1] + dcv * j; cv[2] = 0.0; ecv2 (0) = cv[0]; ecv2 (1) = cv[1]; ecv2 (2) = cv[2]; ecv_t2 = eigenvectors * ecv2 + emean2; if (flip) nurbs.SetCV (nurbs.Order (0) - 1 - i, j, cv_t); else nurbs.SetCV (i, j, cv_t); } } return nurbs; }
ON_NurbsSurface FittingSurface::initNurbsPCABoundingBox (int order, NurbsDataSurface *m_data, Eigen::Vector3d z) { Eigen::Vector3d mean; Eigen::Matrix3d eigenvectors; Eigen::Vector3d eigenvalues; unsigned s = m_data->interior.size (); m_data->interior_param.clear (); NurbsTools::pca (m_data->interior, mean, eigenvectors, eigenvalues); m_data->mean = mean; m_data->eigenvectors = eigenvectors; bool flip (false); if (eigenvectors.col (2).dot (z) < 0.0) flip = true; eigenvalues = eigenvalues / s; // seems that the eigenvalues are dependent on the number of points (???) Eigen::Matrix3d eigenvectors_inv = eigenvectors.inverse (); Eigen::Vector3d v_max (0.0, 0.0, 0.0); Eigen::Vector3d v_min (DBL_MAX, DBL_MAX, DBL_MAX); for (unsigned i = 0; i < s; i++) { Eigen::Vector3d p = eigenvectors_inv * (m_data->interior[i] - mean); m_data->interior_param.push_back (Eigen::Vector2d (p (0), p (1))); if (p (0) > v_max (0)) v_max (0) = p (0); if (p (1) > v_max (1)) v_max (1) = p (1); if (p (2) > v_max (2)) v_max (2) = p (2); if (p (0) < v_min (0)) v_min (0) = p (0); if (p (1) < v_min (1)) v_min (1) = p (1); if (p (2) < v_min (2)) v_min (2) = p (2); } for (unsigned i = 0; i < s; i++) { Eigen::Vector2d &p = m_data->interior_param[i]; if (v_max (0) > v_min (0) && v_max (0) > v_min (0)) { p (0) = (p (0) - v_min (0)) / (v_max (0) - v_min (0)); p (1) = (p (1) - v_min (1)) / (v_max (1) - v_min (1)); } else { throw std::runtime_error ("[NurbsTools::initNurbsPCABoundingBox] Error: v_max <= v_min"); } } ON_NurbsSurface nurbs (3, false, order, order, order, order); nurbs.MakeClampedUniformKnotVector (0, 1.0); nurbs.MakeClampedUniformKnotVector (1, 1.0); double dcu = (v_max (0) - v_min (0)) / (nurbs.Order (0) - 1); double dcv = (v_max (1) - v_min (1)) / (nurbs.Order (1) - 1); Eigen::Vector3d cv_t, cv; for (int i = 0; i < nurbs.Order (0); i++) { for (int j = 0; j < nurbs.Order (1); j++) { cv (0) = v_min (0) + dcu * i; cv (1) = v_min (1) + dcv * j; cv (2) = 0.0; cv_t = eigenvectors * cv + mean; if (flip) nurbs.SetCV (nurbs.Order (0) - 1 - i, j, ON_3dPoint (cv_t (0), cv_t (1), cv_t (2))); else nurbs.SetCV (i, j, ON_3dPoint (cv_t (0), cv_t (1), cv_t (2))); } } return nurbs; }