bool ON_PolyEdgeCurve::EvSrfTangent( double t, bool bIsoDir, ON_3dPoint& srfpoint, ON_3dVector& srftangent, ON_3dVector& srfnormal ) const { ON_3dPoint srfpt; ON_3dVector du, dv, duu, duv, dvv; bool rc = EvSrfDerivatives(t,srfpoint,du,dv,duu,duv,dvv); if (rc ) rc = ON_EvNormal( 0, du, dv, duu, duv, dvv, srfnormal ) ? true : false; if (rc) { int segment_index = SegmentIndex(t); ON_PolyEdgeSegment* seg = SegmentCurve(segment_index); if ( seg ) { if ( bIsoDir && seg->IsoType() == ON_Surface::not_iso ) bIsoDir = false; ON_3dVector crvtangent = TangentAt(t); ON_3dVector binormal = ON_CrossProduct(crvtangent,srfnormal); binormal.Unitize(); if ( seg->ReversedTrimDir() ) binormal.Reverse(); // at this point, binormal points "out" and is tangent // to the surface. if ( bIsoDir ) { du.Unitize(); dv.Unitize(); double B_dot_du = binormal*du; double B_dot_dv = binormal*dv; if ( fabs(B_dot_dv) > fabs(B_dot_du) ) { if (B_dot_dv < 0.0) dv.Reverse(); srftangent = dv; } else { if (B_dot_du < 0.0) du.Reverse(); srftangent = du; } } else srftangent = binormal; if ( seg && seg->m_face && seg->m_face->m_bRev ) srfnormal.Reverse(); } else rc = false; } return rc; }
ON_3dVector ON_Light::PerpindicularDirection() const { // returns a consistent vector perpendicular to the // light's direction. This vector is useful for // user interface display. ON_3dVector dir = m_direction; if ( !dir.IsValid() || !dir.Unitize() ) return ON_UNSET_VECTOR; ON_3dVector xdir; if ( IsLinearLight() || IsRectangularLight() ) { xdir = m_length; if ( xdir.IsValid() && xdir.Unitize() && fabs(xdir*dir) <= ON_SQRT_EPSILON ) return xdir; } if( dir.IsParallelTo( ON_zaxis, ON_DEGREES_TO_RADIANS * 3.0)) xdir = ON_CrossProduct( dir, ON_xaxis); else xdir = ON_CrossProduct( dir, ON_zaxis); xdir.Unitize(); ON_3dVector ydir = ON_CrossProduct(dir,xdir); ydir.Unitize(); ON_3dVector right; switch(dir.MaximumCoordinateIndex()) { case 0: right = (fabs(xdir.y) > fabs(ydir.y)) ? xdir : ydir; if ( right.y < 0.0 ) right.Reverse(); break; case 1: case 2: right = (fabs(xdir.x) > fabs(ydir.x)) ? xdir : ydir; if ( right.x < 0.0 ) right.Reverse(); break; default: right = xdir; break; } if ( right[right.MaximumCoordinateIndex()] < 0.0 ) right.Reverse(); return right; }
ON_BOOL32 ON_ArcCurve::SetStartPoint(ON_3dPoint start_point) { if (IsCircle()) return false; ON_BOOL32 rc = false; if ( m_dim == 3 || start_point.z == 0.0 ) { ON_3dPoint P; ON_3dVector T; double t = Domain()[1]; Ev1Der( t, P, T ); T.Reverse(); ON_Arc a; rc = a.Create( P, T, start_point ); if ( rc ) { a.Reverse(); m_arc = a; } else { ON_3dPoint end_point = PointAt(Domain()[1]); if (end_point.DistanceTo(start_point) < ON_ZERO_TOLERANCE*m_arc.Radius()){ //make arc into circle m_arc.plane.xaxis = end_point - m_arc.Center(); m_arc.plane.xaxis.Unitize(); m_arc.plane.yaxis = ON_CrossProduct(m_arc.Normal(), m_arc.plane.xaxis); m_arc.plane.yaxis.Unitize(); m_arc.SetAngleRadians(2.0*ON_PI); rc = true; } } } return rc; }