RH_C_FUNCTION int ON_RayShooter_OneSurface(ON_3DPOINT_STRUCT _point, ON_3DVECTOR_STRUCT _direction, const ON_Surface* pConstSurface, ON_SimpleArray<ON_3dPoint>* pPoints, int maxReflections) { int rc = 0; ON_3dPoint point(_point.val[0], _point.val[1], _point.val[2]); ON_3dVector direction(_direction.val[0], _direction.val[1], _direction.val[2]); if( pConstSurface && pPoints && maxReflections>0 && point.IsValid() && direction.Unitize() ) { ON_RayShooter shooter; ON_X_EVENT hit; ON_3dPoint Q = point; ON_3dVector R = direction; ON_3dVector V[3]; for( int i=0; i<maxReflections; i++ ) { memset(&hit,0,sizeof(hit)); ON_3dVector T = R; if( !T.Unitize() ) break; if( !shooter.Shoot(Q,T,pConstSurface,hit) ) break; Q = hit.m_A[0]; pPoints->Append(Q); if( !hit.m_snodeB[0] ) break; hit.m_snodeB[0]->Evaluate(hit.m_b[0], hit.m_b[1], 1, 3, &V[0].x); ON_3dVector N = ON_CrossProduct(V[1],V[2]); if ( !N.Unitize() ) break; double d = N*T; R = T + (-2.0*d)*N; // R = reflection direction } rc = pPoints->Count(); } return rc; }
int ON_Box::IsDegenerate( double tolerance ) const { int rc = 0; // 0 box is not degenerate // 1 box is a rectangle (degenerate in one direction) // 2 box is a line (degenerate in two directions) // 3 box is a point (degenerate in three directions) // 4 box is not valid if ( !dx.IsIncreasing() || !dy.IsIncreasing() || !dz.IsIncreasing() ) { rc = 4; } else { const ON_3dVector diag(dx.Length(),dy.Length(),dz.Length()); if ( !ON_IsValid(tolerance) || tolerance < 0.0 ) { // compute scale invarient tolerance tolerance = diag.MaximumCoordinate()*ON_SQRT_EPSILON; } if ( diag.x <= tolerance ) rc++; if ( diag.y <= tolerance ) rc++; if ( diag.z <= tolerance ) rc++; } return rc; }
ON_BOOL32 ON_Light::Transform( const ON_Xform& xform ) { ON_3dVector v; double vlen; TransformUserData(xform); m_location = xform*m_location; v = xform*m_direction; vlen = v.Length(); if ( vlen > 0.0 ) { m_direction = v; } v = xform*m_length; vlen = v.Length(); if ( vlen > 0.0 ) { m_length = v; } v = xform*m_width; vlen = v.Length(); if ( vlen > 0.0 ) { m_width = v; } return true; }
CRhinoCommand::result CCommandSampleMoveCPlane::RunCommand( const CRhinoCommandContext& context ) { CRhinoView* view = ::RhinoApp().ActiveView(); if( !view ) return CRhinoCommand::failure; ON_3dmConstructionPlane cplane = view->Viewport().ConstructionPlane(); ON_3dPoint origin = cplane.m_plane.origin; CSampleMoveCPlanePoint gp( cplane ); gp.SetCommandPrompt( L"CPlane origin" ); gp.SetBasePoint( origin ); gp.DrawLineFromPoint( origin, TRUE ); gp.GetPoint(); if( gp.CommandResult() != CRhinoCommand::success ) return gp.CommandResult(); ON_3dPoint pt = gp.Point(); ON_3dVector v = origin - pt; if( v.IsTiny() ) return CRhinoCommand::nothing; cplane.m_plane.CreateFromFrame( pt, cplane.m_plane.xaxis, cplane.m_plane.yaxis ); view->Viewport().SetConstructionPlane( cplane ); view->Redraw(); return CRhinoCommand::success; }
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; }
ON_BOOL32 ON_Torus::ClosestPointTo( ON_3dPoint test_point, double* major__angle_radians, double* minor__angle_radians ) const { double major_angle_radians, minor_angle_radians; const ON_Circle major_circle(plane,major_radius); ON_BOOL32 rc = major_circle.ClosestPointTo( test_point, &major_angle_radians ); if ( rc && minor__angle_radians ) { EVAL_SETUP_MAJOR; ON_3dVector v = test_point - major_radius*raxis; rc = v.Unitize(); if ( rc ) { double sma = v*plane.zaxis; double cma = v*raxis; minor_angle_radians = atan2(sma,cma); if ( minor_angle_radians < 0.0 ) minor_angle_radians += 2.0*ON_PI; } else minor_angle_radians = 0.0; *minor__angle_radians = minor_angle_radians; } if ( major__angle_radians ) *major__angle_radians = major_angle_radians; return rc; }
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_Ellipse::TangentAt( double t // parameter ) const { ON_3dVector T = DerivativeAt( 1, t ); T.Unitize(); return T; }
// ON_BoundingBox::MaximumDistance has a copy/paste bug in it in V4. Using local // version of this function with the fix so things continue to work under V4 grasshopper static double RhCmnMaxDistance_Helper(const ON_BoundingBox& bbox, const ON_3dPoint& P) { ON_3dVector V; V.x = ( (P.x < 0.5*(bbox.m_min.x+bbox.m_max.x)) ? bbox.m_max.x : bbox.m_min.x) - P.x; V.y = ( (P.y < 0.5*(bbox.m_min.y+bbox.m_max.y)) ? bbox.m_max.y : bbox.m_min.y) - P.y; V.z = ( (P.z < 0.5*(bbox.m_min.z+bbox.m_max.z)) ? bbox.m_max.z : bbox.m_min.z) - P.z; return V.Length(); }
int ON_PlaneSurface::GetNurbForm( // returns 0: unable to create NURBS representation // with desired accuracy. // 1: success - returned NURBS parameterization // matches the surface's to wthe desired accuracy // 2: success - returned NURBS point locus matches // the surfaces's to the desired accuracy but, on // the interior of the surface's domain, the // surface's parameterization and the NURBS // parameterization may not match to the // desired accuracy. ON_NurbsSurface& nurbs, double tolerance ) const { ON_BOOL32 rc = IsValid(); if( !rc ) { if ( m_plane.origin.x != ON_UNSET_VALUE && m_plane.xaxis.x != ON_UNSET_VALUE && m_plane.yaxis.x != ON_UNSET_VALUE && m_domain[0].IsIncreasing() && m_domain[1].IsIncreasing() && m_extents[0].Length() > 0.0 && m_extents[1].Length() > 0.0 ) { ON_3dVector N = ON_CrossProduct(m_plane.xaxis,m_plane.yaxis); if ( N.Length() <= 1.0e-4 ) { ON_WARNING("ON_PlaneSurface::GetNurbForm - using invalid surface."); rc = true; } } } if ( rc ) { nurbs.m_dim = 3; nurbs.m_is_rat = 0; nurbs.m_order[0] = nurbs.m_order[1] = 2; nurbs.m_cv_count[0] = nurbs.m_cv_count[1] = 2; nurbs.m_cv_stride[1] = nurbs.m_dim; nurbs.m_cv_stride[0] = nurbs.m_cv_stride[1]*nurbs.m_cv_count[1]; nurbs.ReserveCVCapacity(12); nurbs.ReserveKnotCapacity(0,2); nurbs.ReserveKnotCapacity(1,2); nurbs.m_knot[0][0] = m_domain[0][0]; nurbs.m_knot[0][1] = m_domain[0][1]; nurbs.m_knot[1][0] = m_domain[1][0]; nurbs.m_knot[1][1] = m_domain[1][1]; nurbs.SetCV( 0, 0, PointAt( m_domain[0][0], m_domain[1][0] )); nurbs.SetCV( 0, 1, PointAt( m_domain[0][0], m_domain[1][1] )); nurbs.SetCV( 1, 0, PointAt( m_domain[0][1], m_domain[1][0] )); nurbs.SetCV( 1, 1, PointAt( m_domain[0][1], m_domain[1][1] )); } return rc; }
ON_3dVector ON_Polyline::SegmentDirection( int segment_index ) const { ON_3dVector v; if ( segment_index >= 0 && segment_index < m_count-1 ) { v = m_a[segment_index+1] - m_a[segment_index]; } else { v.Zero(); } return v; }
bool ON_Cone::ClosestPointTo( ON_3dPoint point, double* radial_parameter, double* height_parameter ) const { // untested code bool rc = false; ON_3dVector v = (point-plane.origin); double x = v*plane.xaxis; double y = v*plane.yaxis; double z = v*plane.zaxis; if ( radial_parameter ) { double a = ( 0.0 == y && 0.0 == x ) ? 0.0 : atan2(y,x); if (a > 2.0*ON_PI ) { a -= 2.0*ON_PI; } if (a < 0.0 ) { a += 2.0*ON_PI; } *radial_parameter = a; } if (height_parameter) { point.x -= plane.origin.x; point.y -= plane.origin.y; point.z -= plane.origin.z; v.x = x; v.y = y; v.z = 0.0; v.Unitize(); v.x *= radius; v.y *= radius; ON_Line line(ON_origin, v.x*plane.xaxis + v.y*plane.yaxis + height*plane.zaxis ); rc = line.ClosestPointTo(point,&z); if (rc) { *height_parameter = z*height; } } return rc; }
ON_3dPoint ON_Torus::ClosestPointTo( ON_3dPoint test_point ) const { const ON_Circle major_circle(plane,major_radius); ON_3dPoint C = major_circle.ClosestPointTo( test_point ); ON_3dVector v = test_point - C; if ( !v.Unitize() ) { v = C - plane.origin; v.Unitize(); } return C + minor_radius*v; }
ON_3dPoint ON_Circle::ClosestPointTo( const ON_3dPoint& point ) const { ON_3dPoint P; ON_3dVector V = plane.ClosestPointTo( point ) - Center(); if ( V.Unitize() ) { V.Unitize(); P = Center() + Radius()*V; } else { P = PointAt(0.0); } return P; }
// Try to make up a 1st derivative if one is zero length static void CookDerivativesHelper( ON_3dVector& du, ON_3dVector& dv, ON_3dVector& duu, ON_3dVector& duv, ON_3dVector& dvv) { bool du_ok = du.LengthSquared() > ON_SQRT_EPSILON; bool dv_ok = dv.LengthSquared() > ON_SQRT_EPSILON; if( !du_ok || !dv_ok) { ON_3dVector normal; bool normal_ok = ON_EvNormal( 0, du, dv, duu, duv, dvv, normal ) ? true : false; if( normal_ok) normal_ok = normal.LengthSquared() > ON_SQRT_EPSILON; if( normal_ok) { if(( !du_ok) && ( dv_ok && normal_ok)) { du = ON_CrossProduct( dv, normal); du_ok = du.Unitize(); du *= (0.00390625*dv.Length()); } if( du_ok && ( !dv_ok) && normal_ok) { dv = ON_CrossProduct( normal, du); dv_ok = dv.Unitize(); dv *= (0.00390625*du.Length()); } } } }
ON_3dVector ON_Cone::NormalAt( double radial_parameter, double height_parameter ) const { double s = sin(radial_parameter); double c = cos(radial_parameter); if ( radius<0.) { c = -c; s = -s; } ON_3dVector ds = c*plane.yaxis - s*plane.xaxis; ON_3dVector N = ON_CrossProduct( ((radius<0.0)?-ds:ds), plane.PointAt(radius*c,radius*s,height) - plane.origin ); N.Unitize(); return N; }
bool ON_Plane::CreateFromFrame( const ON_3dPoint& P, // point on the plane const ON_3dVector& X, // non-zero vector in plane const ON_3dVector& Y // another non-zero vector in the plane ) { origin = P; xaxis = X; xaxis.Unitize(); yaxis = Y - ON_DotProduct( Y, xaxis)*xaxis; yaxis.Unitize(); zaxis = ON_CrossProduct( xaxis, yaxis ); bool b = zaxis.Unitize(); UpdateEquation(); if ( b ) { // 11 February 2004 Dale Lear // Add more validation checks. b = IsValid(); if ( b ) { // make sure zaxis is perp to Y if ( fabs(Y*zaxis) > ON_SQRT_EPSILON*Y.Length() ) b = false; } } return b; }
ON_BOOL32 ON_Geometry::Translate( const ON_3dVector& delta ) { if ( delta.IsZero() ) return true; ON_Xform tr; tr.Translation( delta ); return Transform( tr ); }
RH_C_FUNCTION ON_AngularDimension2* ON_AngularDimension2_New(ON_Arc* arc, double offset) { ON_AngularDimension2* rc = NULL; if( arc ) { rc = new ON_AngularDimension2(); ON_3dVector v = arc->StartPoint()-arc->Center(); v.Unitize(); ON_3dPoint apex = arc->Center(); ON_3dPoint p0 = arc->StartPoint(); ON_3dPoint p1 = arc->EndPoint(); ON_3dPoint arc_pt = p0 + ( v * offset ); ON_3dVector normal = arc->Normal(); rc->CreateFromPoints(apex, p0, p1, arc_pt, normal); } return rc; }
bool ON_Localizer::CreatePlaneLocalizer( ON_3dPoint P, ON_3dVector N, double h0, double h1 ) { Destroy(); if ( P.IsValid() && N.IsValid() && N.Length() > 0.0 && ON_IsValid(h0) && ON_IsValid(h1) && h0 != h1 ) { m_V = N; m_V.Unitize(); m_P.Set( -(m_V.x*P.x + m_V.y*P.y + m_V.z*P.z), 0.0, 0.0 ); m_d.Set(h0,h1); m_type = plane_type; } return (plane_type == m_type); }
static bool ON_BrepExtrudeHelper_CheckPathCurve( const ON_Curve& path_curve, ON_3dVector& path_vector ) { ON_Line path_line; path_line.from = path_curve.PointAtStart(); path_line.to = path_curve.PointAtEnd(); path_vector = path_line.Direction(); return ( path_vector.IsZero() ? false : true ); }
void arbaxis(const ON_3dVector& givenaxis, ON_3dVector& newaxis) { if(fabs(givenaxis[0]) < ARBBOUND && fabs(givenaxis[1]) < ARBBOUND) // near world z newaxis = ON_CrossProduct(ON_yaxis, givenaxis); else newaxis = ON_CrossProduct(ON_zaxis, givenaxis); newaxis.Unitize(); }
ON_Surface* ON_PlaneSurface::Offset( double offset_distance, double tolerance, double* max_deviation ) const { if ( max_deviation ) *max_deviation = 0.0; ON_PlaneSurface* offset_srf = new ON_PlaneSurface(*this); ON_3dVector delta = offset_srf->m_plane.zaxis; double d = delta.Length(); if ( fabs(1.0-d) <= ON_SQRT_EPSILON ) d = 1.0; d = offset_distance/d; offset_srf->m_plane.origin = offset_srf->m_plane.origin + (d*delta); offset_srf->m_plane.UpdateEquation(); return offset_srf; }
bool ON_Quaternion::GetRotation(double& angle, ON_3dVector& axis) const { const double s = Length(); angle = (s > ON_DBL_MIN) ? 2.0*acos(a/s) : 0.0; axis.x = b; axis.y = c; axis.z = d; return (axis.Unitize() && s > ON_DBL_MIN); }
void ON_Quaternion::SetRotation(double angle, const ON_3dVector& axis) { double s = axis.Length(); s = (s > 0.0) ? sin(0.5*angle)/s : 0.0; a = cos(0.5*angle); b = s*axis.x; c = s*axis.y; d = s*axis.z; }
int ON_Intersect( // returns 0 = no intersections, // 1 = one intersection, // 2 = 2 intersections // If 0 is returned, first point is point // on line closest to sphere and 2nd point is the point // on the sphere closest to the line. // If 1 is returned, first point is obtained by evaluating // the line and the second point is obtained by evaluating // the sphere. const ON_Line& line, const ON_Sphere& sphere, ON_3dPoint& A, ON_3dPoint& B // intersection point(s) returned here ) { int rc = 0; const ON_3dPoint sphere_center = sphere.plane.origin; const double sphere_radius = fabs(sphere.radius); double tol = sphere_radius*ON_SQRT_EPSILON; if ( tol < ON_ZERO_TOLERANCE ) tol = ON_ZERO_TOLERANCE; ON_3dPoint line_center = line.ClosestPointTo(sphere_center); double d = line_center.DistanceTo(sphere_center); if ( d >= sphere_radius-tol ) { rc = ( d <= sphere_radius-tol ) ? 1 : 0; A = line_center; B = sphere.ClosestPointTo(line_center); } else { d /= sphere_radius; double h = sphere_radius*sqrt(1.0 - d*d); ON_3dVector V = line.Direction(); V.Unitize(); A = sphere.ClosestPointTo(line_center - h*V); B = sphere.ClosestPointTo(line_center + h*V); d = A.DistanceTo(B); if ( d <= ON_ZERO_TOLERANCE ) { A = line_center; B = sphere.ClosestPointTo(line_center); rc = 1; } else rc = 2; } return rc; }
bool ON_Line::InPlane( ON_Plane& plane, double tolerance ) const { const ON_3dVector v = to-from; const bool bTinyX = fabs(v.x) <= tolerance; const bool bTinyY = fabs(v.y) <= tolerance; const bool bTinyZ = fabs(v.z) <= tolerance; bool rc = true; ON_3dVector X; ON_3dVector Y; if ( bTinyZ && ( !bTinyX || !bTinyY ) ) { X = ON_xaxis; Y = ON_yaxis; } else if ( bTinyX && ( !bTinyY || !bTinyZ ) ) { X = ON_yaxis; Y = ON_zaxis; } else if ( bTinyY && ( !bTinyZ || !bTinyX ) ) { X = ON_zaxis; Y = ON_xaxis; } else { X = v; X.Unitize(); Y.PerpendicularTo(X); if ( bTinyX && bTinyY && bTinyZ ) { rc = false; if ( X.IsZero() ) { X = ON_xaxis; Y = ON_yaxis; } } } plane.CreateFromFrame( from, X, Y ); return rc; }
bool ON_Localizer::CreateCylinderLocalizer( ON_3dPoint P, ON_3dVector V, double r0, double r1 ) { Destroy(); if ( P.IsValid() && V.IsValid() && V.Length() > 0.0 && ON_IsValid(r0) && ON_IsValid(r1) && r0 > 0.0 && r1 > 0.0 && r0 != r1 ) { m_P = P; m_V = V; m_V.Unitize(); m_d.Set(r0,r1); m_type = cylinder_type; } return (cylinder_type == m_type); }
static double Angle3d(const ON_3dVector& axis, ON_3dVector& from, const ON_3dVector& to) { ON_3dVector x = from, a = to; x.Unitize(); a.Unitize(); ON_3dVector y = ON_CrossProduct(axis, from); y.Unitize(); double cosa = x * a; if(cosa > 1.0 - ON_SQRT_EPSILON) return 0.0; if(cosa < ON_SQRT_EPSILON - 1.0) return ON_PI; double sina = a * y; return atan2(sina, cosa); }
bool ON_Line::ClosestPointTo( const ON_3dPoint& point, double *t ) const { bool rc = false; if ( t ) { const ON_3dVector D = Direction(); const double DoD = D.LengthSquared(); if ( DoD > 0.0 ) { if ( point.DistanceTo(from) <= point.DistanceTo(to) ) { *t = ((point - from)*D)/DoD; } else { *t = 1.0 + ((point - to)*D)/DoD; } rc = true; } else { *t = 0.0; } } return rc; }