ON_BOOL32 ON_PlaneSurface::GetSpanVector( int dir, double* s ) const { ON_Interval d = Domain(dir); s[0] = d.Min(); s[1] = d.Max(); return d.IsIncreasing(); }
ON_BOOL32 ON_Surface::GetParameterTolerance( // returns tminus < tplus: parameters tminus <= s <= tplus int dir, double t, // t = parameter in domain double* tminus, // tminus double* tplus // tplus ) const { ON_BOOL32 rc = false; ON_Interval d = Domain( dir ); if ( d.IsIncreasing() ) rc = ON_GetParameterTolerance( d.Min(), d.Max(), t, tminus, tplus ); return rc; }
ON_Surface::ISO ON_Surface::IsIsoparametric( const ON_BoundingBox& bbox ) const { ISO iso = not_iso; if ( bbox.m_min.z == bbox.m_max.z ) { const double ds = bbox.m_max.x - bbox.m_min.x; const double dt = bbox.m_max.y - bbox.m_min.y; double a, b, s0, s1, t0, t1; ON_Interval d = Domain(0); s0 = d.Min(); s1 = d.Max(); d = Domain(1); t0 = d.Min(); t1 = d.Max(); double stol = (s1-s0)/32.0; double ttol = (t1-t0)/32.0; if ( s0 < s1 && t0 < t1 && ( ds <= stol || dt <= ttol) ) { if ( ds*(t1-t0) <= dt*(s1-s0) ) { // check for s = constant iso if ( bbox.m_max.x <= s0+stol ) { // check for west side iso GetParameterTolerance( 0, s0, &a, &b); if ( a <= bbox.m_min.x && bbox.m_max.x <= b ) iso = W_iso; } else if ( bbox.m_min.x >= s1-stol ) { // check for east side iso GetParameterTolerance( 0, s1, &a, &b); if ( a <= bbox.m_min.x && bbox.m_max.x <= b ) iso = E_iso; } if ( iso == not_iso && (s0 < bbox.m_max.x || bbox.m_min.x < s1) ) { // check for interior "u = constant" iso GetParameterTolerance( 0, 0.5*(bbox.m_min.x+bbox.m_max.x), &a, &b); if ( a <= bbox.m_min.x && bbox.m_max.x <= b ) iso = x_iso; } } else { // check for t = constant iso if ( bbox.m_max.y <= t0+ttol ) { // check for south side iso GetParameterTolerance( 1, t0, &a, &b); if ( a < bbox.m_min.y && bbox.m_max.y <= b ) iso = S_iso; } else if ( bbox.m_min.y >= t1-ttol ) { // check for north side iso GetParameterTolerance( 1, t1, &a, &b); if ( a < bbox.m_min.y && bbox.m_max.y <= b ) iso = N_iso; } if ( iso == not_iso && (t0 < bbox.m_max.x || bbox.m_min.x < t1) ) { // check for interior "t = constant" iso GetParameterTolerance( 1, 0.5*(bbox.m_min.y+bbox.m_max.y), &a, &b); if ( a < bbox.m_min.y && bbox.m_max.y <= b ) iso = y_iso; } } } } return iso; }
ON_BOOL32 ON_Surface::EvNormal( // returns false if unable to evaluate double s, double t, // evaluation parameters (s,t) ON_3dPoint& point, // returns value of surface ON_3dVector& ds, // first partial derivatives (Ds) ON_3dVector& dt, // (Dt) ON_3dVector& normal, // unit normal int side, // optional - determines which side to evaluate from // 0 = default // 1 from NE quadrant // 2 from NW quadrant // 3 from SW quadrant // 4 from SE quadrant int* hint // optional - evaluation hint (int[2]) used to speed // repeated evaluations ) const { // simple cross product normal - override to support singular surfaces ON_BOOL32 rc = Ev1Der( s, t, point, ds, dt, side, hint ); if ( rc ) { const double len_ds = ds.Length(); const double len_dt = dt.Length(); // do not reduce the tolerance used here - there is a retry in the code // below. if ( len_ds > ON_SQRT_EPSILON*len_dt && len_dt > ON_SQRT_EPSILON*len_ds ) { ON_3dVector a = ds/len_ds; ON_3dVector b = dt/len_dt; normal = ON_CrossProduct( a, b ); rc = normal.Unitize(); } else { // see if we have a singular point double v[6][3]; int normal_side = side; ON_BOOL32 bOnSide = false; ON_Interval sdom = Domain(0); ON_Interval tdom = Domain(1); if (s == sdom.Min()) { normal_side = (normal_side >= 3) ? 4 : 1; bOnSide = true; } else if (s == sdom.Max()) { normal_side = (normal_side >= 3) ? 3 : 2; bOnSide = true; } if (t == tdom.Min()) { normal_side = (normal_side == 2 || normal_side == 3) ? 2 : 1; bOnSide = true; } else if (t == tdom.Max()) { normal_side = (normal_side == 2 || normal_side == 3) ? 3 : 4; bOnSide = true; } if ( !bOnSide ) { // 2004 November 11 Dale Lear // Added a retry again with a more generous tolerance if ( len_ds > ON_EPSILON*len_dt && len_dt > ON_EPSILON*len_ds ) { ON_3dVector a = ds/len_ds; ON_3dVector b = dt/len_dt; normal = ON_CrossProduct( a, b ); rc = normal.Unitize(); } else { rc = false; } } else { rc = Evaluate( s, t, 2, 3, &v[0][0], normal_side, hint ); if ( rc ) { rc = ON_EvNormal( normal_side, v[1], v[2], v[3], v[4], v[5], normal); } } } } if ( !rc ) { normal.Zero(); } return rc; }