int ON_LineCurve::GetNurbForm( ON_NurbsCurve& c, double tolerance, const ON_Interval* subdomain ) const { int rc = 0; if ( c.Create( m_dim==2?2:3, false, 2, 2 ) ) { rc = 1; double t0 = m_t[0]; double t1 = m_t[1]; if (subdomain ) { if ( t0 < t1 ) { const ON_Interval& sd = *subdomain; double s0 = sd[0]; double s1 = sd[1]; if (s0 < t0) s0 = t0; if (s1 > t1) s1 = t1; if (s0 < s1) { t0 = s0; t1 = s1; } else rc = 0; } else { rc = 0; } } if ( t0 < t1 ) { c.m_knot[0] = t0; c.m_knot[1] = t1; c.SetCV( 0, PointAt(t0)); c.SetCV( 1, PointAt(t1)); } else if ( t0 > t1 ) { rc = 0; c.m_knot[0] = t1; c.m_knot[1] = t0; c.SetCV( 0, PointAt(t1)); c.SetCV( 1, PointAt(t0)); } else { rc = 0; c.m_knot[0] = 0.0; c.m_knot[1] = 1.0; c.SetCV( 0, m_line.from ); c.SetCV( 1, m_line.to ); } } return rc; }
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; }
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; }
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; }
int ON_CurveProxy::GetNurbForm( // returns 0: unable to create NURBS representation // with desired accuracy. // 1: success - returned NURBS parameterization // matches the curve's to wthe desired accuracy // 2: success - returned NURBS point locus matches // the curve's to the desired accuracy but, on // the interior of the curve's domain, the // curve's parameterization and the NURBS // parameterization may not match to the // desired accuracy. ON_NurbsCurve& nurbs, double tolerance, // (>=0) const ON_Interval* sub_domain // OPTIONAL subdomain of ON::ProxyCurve::Domain() ) const { ON_BOOL32 rc = false; if ( m_real_curve ) { ON_Interval scratch_domain = RealCurveInterval( sub_domain ); rc = m_real_curve->GetNurbForm(nurbs,tolerance,&scratch_domain); if ( rc ) { if ( m_bReversed ) nurbs.Reverse(); ON_Interval d = m_this_domain; if ( sub_domain ) d.Intersection( *sub_domain ); nurbs.SetDomain( d[0], d[1] ); if ( nurbs.m_dim <= 3 && nurbs.m_dim >= 1 ) { double t0 = Domain()[0]; double t1 = Domain()[1]; if ( 0 != sub_domain ) { if ( t0 < sub_domain->Min() ) t0 = sub_domain->Min(); if ( sub_domain->Max() < t1 ) t1 = sub_domain->Max(); } // set ends of NURBS curve to be exactly on ends of proxy curve ON_3dPoint P0 = PointAt(t0); ON_3dPoint P1 = PointAt(t1); ON_3dPoint N0 = nurbs.PointAtStart(); ON_3dPoint N1 = nurbs.PointAtEnd(); // 22 September 2003, GBA. The end tuning code below should only be applied // to clamped nurbs curves. In particular it should not be used on // periodic nurbs curves. Fixes TRR#11502. ON_BOOL32 clamped = nurbs.IsClamped(2); if ( clamped && (P0 != N0 || P1 != N1) ) { if ( 0==nurbs.m_is_rat ) { nurbs.SetCV(0,P0); nurbs.SetCV(nurbs.m_cv_count-1,P1); } else { ON_4dPoint H0, H1; H0 = P0; H0.w = nurbs.Weight(0); H0.x *= H0.w; H0.y *= H0.w; H0.z *= H0.w; nurbs.SetCV(0,H0); H1 = P1; H1.w = nurbs.Weight(nurbs.m_cv_count-1); H1.x *= H1.w; H1.y *= H1.w; H1.z *= H1.w; nurbs.SetCV(nurbs.m_cv_count-1,H1); } } } } } return rc; }