ON_Interval ON_CurveProxy::RealCurveInterval( const ON_Interval* sub_domain ) const { if ( !sub_domain ) return m_real_curve_domain; ON_Interval d = m_this_domain; d.Intersection(*sub_domain); double t0 = RealCurveParameter( d[m_bReversed?1:0] ); double t1 = RealCurveParameter( d[m_bReversed?0:1] ); return ON_Interval(t0,t1); }
void ON_CurveProxy::SetProxyCurve( const ON_Curve* real_curve, ON_Interval real_curve_subdomain) { if ( real_curve != this ) { // setting m_real_curve=0 prevents crashes if user has deleted // the "real" curve before calling SetProxyCurve(). m_real_curve = 0; DestroyCurveTree(); m_real_curve_domain.Destroy(); m_this_domain.Destroy(); m_bReversed = false; } else { // If you are debugging and end up here, there is a 99% chance // that you passed the wrong pointer to SetProxyCurve(). // However, I will assume you really meant to use a fancy self // reference to adjust domains. if ( IsValid() && m_this_domain.Includes(real_curve_subdomain) ) { real_curve = m_real_curve; // because input real_curve_subdomain was with respect to "this". double r0 = RealCurveParameter(real_curve_subdomain[0]); double r1 = RealCurveParameter(real_curve_subdomain[1]); real_curve_subdomain.Set(r0,r1); } else { real_curve = 0; } // setting m_real_curve=0 prevents crashes if user has deleted // the "real" curve before calling SetProxyCurve(). m_real_curve = 0; DestroyCurveTree(); } m_real_curve = real_curve; if ( m_real_curve ) { SetProxyCurveDomain( real_curve_subdomain ); } else { m_real_curve_domain = real_curve_subdomain; } m_this_domain = m_real_curve_domain; }
bool ON_CurveProxy::IsContinuous( ON::continuity desired_continuity, double t, int* hint, // default = NULL, double point_tolerance, // default=ON_ZERO_TOLERANCE double d1_tolerance, // default==ON_ZERO_TOLERANCE double d2_tolerance, // default==ON_ZERO_TOLERANCE double cos_angle_tolerance, // default==ON_DEFAULT_ANGLE_TOLERANCE_COSINE double curvature_tolerance // default==ON_SQRT_EPSILON ) const { bool rc = true; if ( m_real_curve ) { if ( m_real_curve_domain != m_real_curve->Domain() ) { // 20 March 2003 Dale Lear // Added this code to correctly handle the new locus // flavors of ON::continuity. switch(desired_continuity) { case ON::unknown_continuity: case ON::C0_continuous: case ON::C1_continuous: case ON::C2_continuous: case ON::G1_continuous: case ON::G2_continuous: case ON::Cinfinity_continuous: case ON::Gsmooth_continuous: break; case ON::C0_locus_continuous: case ON::C1_locus_continuous: case ON::C2_locus_continuous: case ON::G1_locus_continuous: case ON::G2_locus_continuous: if ( t >= Domain()[1] ) { // Since the proxy curve is using a subset of the real curve, // the proxy can't be closed. So if the query parameter // is >= domain max, the curve cannot be locus continuous. rc = false; } else { // otherwise we want the answer for a non-locus test desired_continuity = ON::ParametricContinuity(desired_continuity); } break; } } if (rc) rc = m_real_curve->IsContinuous( desired_continuity, RealCurveParameter(t), hint, point_tolerance, d1_tolerance, d2_tolerance, cos_angle_tolerance, curvature_tolerance ); } return rc; }
ON_BOOL32 ON_CurveProxy::GetLocalClosestPoint( const ON_3dPoint& test_point, double seed_parameter, double* t, const ON_Interval* sub_domain ) const { ON_BOOL32 rc = false; if ( m_real_curve ) { ON_Interval scratch_domain = RealCurveInterval( sub_domain ); double sp = RealCurveParameter(seed_parameter); rc = m_real_curve->GetLocalClosestPoint( test_point, sp, t, &scratch_domain ); if ( rc && t ) *t = ThisCurveParameter(*t); } return rc; }
ON_BOOL32 ON_CurveProxy::GetParameterTolerance( double t, // t = parameter in domain double* tminus, // tminus double* tplus // tplus ) const { ON_BOOL32 rc = ( m_real_curve ) ? m_real_curve->GetParameterTolerance( RealCurveParameter(t),tminus,tplus) : false; if (rc) { if ( tminus ) *tminus = ThisCurveParameter(*tminus); if ( tplus ) *tplus = ThisCurveParameter(*tplus); } return rc; }
ON_BOOL32 ON_CurveProxy::GetNurbFormParameterFromCurveParameter( double curve_t, double* nurbs_t ) const { ON_BOOL32 rc = false; if ( m_real_curve ) { // 18 June 2003 Dale Lear and Chuck // Fixing joining bug in STEP TEST 2 caused by error // in converting NURBS parameter to arc parameter. const ON_Curve* real_crv = m_real_curve; ON_Curve* tmp_real_crv = 0; if ( m_real_curve_domain != m_real_curve->Domain() ) { const ON_ArcCurve* arc_curve = ON_ArcCurve::Cast(m_real_curve); if ( 0 != arc_curve ) { tmp_real_crv = arc_curve->DuplicateCurve(); if ( 0 != tmp_real_crv ) { if ( tmp_real_crv->Trim(m_real_curve_domain) ) { real_crv = tmp_real_crv; } } } } rc = real_crv->GetNurbFormParameterFromCurveParameter( RealCurveParameter(curve_t),nurbs_t); if ( rc ) *nurbs_t = ThisCurveParameter(*nurbs_t); if ( 0 != tmp_real_crv ) delete tmp_real_crv; } return rc; }
// override of virtual ON_Curve::Split ON_BOOL32 ON_CurveProxy::Split( double t, ON_Curve*& left_side, ON_Curve*& right_side ) const { ON_BOOL32 rc = false; if ( m_this_domain.IsIncreasing() && m_real_curve_domain.IsIncreasing() && m_this_domain.Includes(t,true) ) { double crv_t = RealCurveParameter(t); if ( m_real_curve_domain.Includes(crv_t,true) ) { ON_CurveProxy* left_proxy = 0; ON_CurveProxy* right_proxy = 0; if ( left_side ) { left_proxy = ON_CurveProxy::Cast(left_side); if ( !left_proxy ) return false; } if ( right_side ) { right_proxy = ON_CurveProxy::Cast(right_side); if ( !right_proxy ) return false; if ( right_side == left_side ) return false; } bool bRev = m_bReversed; ON_Interval left_real_dom, right_real_dom; if ( bRev ) { left_real_dom.Set(crv_t,m_real_curve_domain[1]); right_real_dom.Set(m_real_curve_domain[0],crv_t); } else { left_real_dom.Set(m_real_curve_domain[0],crv_t); right_real_dom.Set(crv_t,m_real_curve_domain[1]); } ON_Interval left_this_dom(m_this_domain[0],t); ON_Interval right_this_dom(t,m_this_domain[1]); if ( left_real_dom.IsIncreasing() && right_real_dom.IsIncreasing() && left_this_dom.IsIncreasing() && right_this_dom.IsIncreasing() ) { // note well that left_proxy or right_proxy might also be this const ON_Curve* real_crv = m_real_curve; if ( real_crv ) { ON_Interval d = real_crv->Domain(); if ( !d.Includes(left_real_dom) ) return false; if ( !d.Includes(right_real_dom) ) return false; } if ( !left_proxy ) left_proxy = new ON_CurveProxy(); if ( !right_proxy ) right_proxy = new ON_CurveProxy(); left_proxy->SetProxyCurve( real_crv, left_real_dom ); right_proxy->SetProxyCurve( real_crv, right_real_dom ); if ( bRev ) { left_proxy->Reverse(); right_proxy->Reverse(); } left_proxy->SetDomain(left_this_dom[0],left_this_dom[1]); right_proxy->SetDomain(right_this_dom[0],right_this_dom[1]); if (!left_side) left_side = left_proxy; if (!right_side) right_side = right_proxy; rc = true; } } } return rc; }
ON_BOOL32 ON_CurveProxy::Evaluate( // returns false if unable to evaluate double t, // evaluation parameter int der_count, // number of derivatives (>=0) int v_stride, // v[] array stride (>=Dimension()) double* v, // v[] array of length stride*(ndir+1) int side, // optional - determines which side to evaluate from // 0 = default // < 0 to evaluate from below, // > 0 to evaluate from above int* hint // optional - evaluation hint (int) used to speed // repeated evaluations ) const { // When the proxy domain is a proper subdomain of the // real curve and we are evaluating at the end, we // need to be certain we are getting the values // from the active part of the curve. double normt = m_this_domain.NormalizedParameterAt(t); if( fabs( normt )<ON_ZERO_TOLERANCE) side = (abs(side) <= 1) ? 1 : 2; else if( fabs(1.0 - normt)<ON_ZERO_TOLERANCE) side = (abs(side) <= 1) ? -1 : -2; if ( 0 != side ) { if ( m_bReversed ) { side = -side; } if (m_bReversed || m_real_curve_domain != m_this_domain ) { // 9 November 2010 Dale Lear - ON_TuneupEvaluationParameter fix // If we have to adjust the evaluation parameter for the // real curve and the evaluation side was specified, then // set side to +2 or -2 to trigger the use of // ON_TuneupEvaluationParameter() when it matters. if ( -1 == side ) side = -2; else if ( 1 == side ) side = 2; } } double r = RealCurveParameter(t); ON_BOOL32 rc = ( m_real_curve ) ? m_real_curve->Evaluate( r,der_count,v_stride,v,side,hint) : false; if ( rc && m_bReversed ) { // negate odd derivatives const int dim = m_real_curve->Dimension(); int di, i; for ( di = 1; di <= der_count; di+=2 ) { v += v_stride; for ( i = 0; i < dim; i++ ) { v[i] = -v[i]; } v += v_stride; } } return rc; }
bool ON_CurveProxy::GetNextDiscontinuity( ON::continuity c, double t0, double t1, double* t, int* hint, int* dtype, double cos_angle_tolerance, double curvature_tolerance ) const { bool rc = false; if ( 0 != dtype ) *dtype = 0; if ( 0 != m_real_curve ) { double s; // convert to "real" curve parameters double s0 = RealCurveParameter( t0 ); double s1 = RealCurveParameter( t1 ); // 21 October 2005 Dale Lear: // // NOTE: If m_bReversed is true, then RealCurveParameter // will reverse the direction of the search. // The commented out code below just messed things up. // //if ( m_bReversed ) //{ // // NOTE: GetNextDiscontinuity search begins at // // "t0" and goes towards "t1" so it is ok if s0 > s1. // s = s0; s0 = s1; s1 = s; //} ON::continuity parametric_c = ON::ParametricContinuity(c); int realcrv_dtype = 0; bool realcrv_rc = m_real_curve->GetNextDiscontinuity(parametric_c,s0,s1,&s,hint,&realcrv_dtype,cos_angle_tolerance,curvature_tolerance); if ( realcrv_rc ) { double thiscrv_t = ThisCurveParameter(s); if ( !(t0 < thiscrv_t && thiscrv_t < t1) && !(t1 < thiscrv_t && thiscrv_t < t0) ) { realcrv_rc = false; realcrv_dtype = 0; // Sometimes proxy domain adjustments kill all the precision. // To avoid infinite loops, it is critical that *t != t0 double s2 = ON_SQRT_EPSILON*s1 + (1.0 - ON_SQRT_EPSILON)*s0; if ( (s0 < s2 && s2 < s1) || (s1 < s2 && s2 < s0) ) { realcrv_rc = m_real_curve->GetNextDiscontinuity(parametric_c,s2,s1,&s,hint,&realcrv_dtype,cos_angle_tolerance,curvature_tolerance); if ( realcrv_rc ) thiscrv_t = ThisCurveParameter(s); } } if ( realcrv_rc ) { if ( (t0 < thiscrv_t && thiscrv_t < t1) || (t1 < thiscrv_t && thiscrv_t < t0) ) { *t = thiscrv_t; if ( dtype ) *dtype = realcrv_dtype; rc = true; } } } if ( !rc && parametric_c != c ) { // 20 March 2003 Dale Lear: // Let base class test decide locus continuity questions at ends rc = ON_Curve::GetNextDiscontinuity( c, t0, t1, t, hint, dtype, cos_angle_tolerance, curvature_tolerance ); } } return rc; }