/* Description: Selects point cloud points using a 2D selection region. Parameters: view - [in] The view in which the selection region was defined. cloud - [in] The point cloud to test. points3d - [in] The 2D (screen) points that define the selection region. indices - [out] The indices of the points in the point cloud that lie inside of the selection region. Returns: The number of indices added to the output array. */ static int RhRegionSelectPointCloudPoints( CRhinoView* view, const ON_PointCloud& cloud, ON_SimpleArray<CPoint>& points2d, ON_SimpleArray<int>& indices ) { if( 0 == view ) return 0; const int index_count = indices.Count(); CRgn rgn; if( rgn.CreatePolygonRgn(points2d.Array(), points2d.Count(), WINDING) ) { ON_Xform w2s; view->ActiveViewport().VP().GetXform( ON::world_cs, ON::screen_cs, w2s ); int i; ON_3dPoint point; for( i = 0; i < cloud.m_P.Count(); i++ ) { point = cloud.m_P[i]; point.Transform( w2s ); if( rgn.PtInRegion((int)point.x, (int)point.y) ) indices.Append( i ); } } return indices.Count() - index_count; }
static void DumpDistanceABHelper( ON_TextLog& text_log, ON_3dPoint A0, ON_3dPoint B0, ON_3dPoint A1, ON_3dPoint B1 ) { if ( A0.DistanceTo(B0) <= A1.DistanceTo(B0) ) DumpDistanceABHelper( text_log, A0, B0 ); else DumpDistanceABHelper( text_log, A1, B1 ); }
bool ON_BezierCageMorph::Create( ON_3dPoint P0, ON_3dPoint P1, ON_3dPoint P2, ON_3dPoint P3, int point_countX, int point_countY, int point_countZ ) { if ( point_countX < 2 || point_countY < 2 || point_countZ < 2 || !P0.IsValid() || !P1.IsValid() || !P2.IsValid() || !P3.IsValid() ) { ON_ERROR("ON_BezierCageMorph::Create - invalid input"); } m_bValid = false; ON_3dVector X = P1-P0; ON_3dVector Y = P2-P0; ON_3dVector Z = P3-P0; ON_Xform xform(1.0); xform[0][0] = X.x; xform[1][0] = X.y; xform[2][0] = X.z; xform[0][1] = Y.x; xform[1][1] = Y.y; xform[2][1] = Y.z; xform[0][2] = Z.x; xform[1][2] = Z.y; xform[2][2] = Z.z; xform[0][3] = P0.x; xform[1][3] = P0.y; xform[2][3] = P0.z; double min_pivot = 0.0; m_bValid = xform.Invert(&min_pivot); if (m_bValid) { ON_3dPoint box_corners[8]; box_corners[0] = P0; box_corners[1] = P1; box_corners[2] = P0+X+Y; box_corners[3] = P2; box_corners[4] = P3; box_corners[5] = P3+X; box_corners[6] = P3+X+Y; box_corners[7] = P3+Y; m_bValid = m_rst2xyz.Create(box_corners,point_countX,point_countY,point_countZ); m_xyz2rst = xform; } else { ON_ERROR("ON_BezierCageMorph::Create - invalid input - P0,P1,P2,P3 are coplanar"); m_rst2xyz.Destroy(); } return m_bValid; }
/** * \return Point on spline at given position t (0..1). */ RVector RSpline::getPointAt(double t) const { updateInternal(); #ifndef R_NO_OPENNURBS ON_3dPoint p = curve.PointAt(t); if (p.IsUnsetPoint()) { return RVector::invalid; } return RVector(p.x, p.y); #else return RVector::invalid; #endif }
ON_2dPoint BBNode::getClosestPointEstimate(const ON_3dPoint &pt, ON_Interval &u, ON_Interval &v) { if (isLeaf()) { double uvs[5][2] = {{m_u.Min(), m_v.Min()}, {m_u.Max(), m_v.Min()}, {m_u.Max(), m_v.Max()}, {m_u.Min(), m_v.Max()}, {m_u.Mid(), m_v.Mid()} }; /* include the estimate */ ON_3dPoint corners[5]; const ON_Surface *surf = m_face->SurfaceOf(); u = m_u; v = m_v; /* ??? pass these in from SurfaceTree::surfaceBBox() to avoid * this recalculation? */ if (!surf->EvPoint(uvs[0][0], uvs[0][1], corners[0]) || !surf->EvPoint(uvs[1][0], uvs[1][1], corners[1]) || !surf->EvPoint(uvs[2][0], uvs[2][1], corners[2]) || !surf->EvPoint(uvs[3][0], uvs[3][1], corners[3])) { throw new std::exception(); /* FIXME */ } corners[4] = BBNode::m_estimate; /* find the point on the surface closest to pt */ size_t mini = 0; double mindist = pt.DistanceTo(corners[mini]); double tmpdist; for (size_t i = 1; i < 5; i++) { tmpdist = pt.DistanceTo(corners[i]); TRACE("\t" << mindist << " < " << tmpdist); if (tmpdist < mindist) { mini = i; mindist = tmpdist; } } TRACE("Closest: " << mindist << "; " << PT2(uvs[mini])); return ON_2dPoint(uvs[mini][0], uvs[mini][1]); } else { if (m_children.size() > 0) { BBNode *closestNode = m_children[0]; for (size_t i = 1; i < m_children.size(); i++) { closestNode = closer(pt, closestNode, m_children[i]); TRACE("\t" << PT(closestNode->m_estimate)); } return closestNode->getClosestPointEstimate(pt, u, v); } throw new std::exception(); } }
double ON_Localizer::Value(ON_3dPoint P) const { double v,s,t = m_d.m_t[1]; switch ( m_type ) { case cylinder_type: // t = distance from P to axis t = ON_CrossProduct( P-m_P, m_V ).Length(); break; case plane_type: // t = distance above plane t = m_V.x*P.x + m_V.y*P.y + m_V.z*P.z + m_P.x; break; case sphere_type: // t = distance to P t = (P-m_P).Length(); break; case curve_type: if ( !m_nurbs_curve ) return 1.0; if ( !m_nurbs_curve->GetClosestPoint(P,&v) ) return 1.0; t = P.DistanceTo(m_nurbs_curve->PointAt(v)); break; case surface_type: if ( !m_nurbs_surface ) return 1.0; if ( !m_nurbs_surface->GetClosestPoint(P,&s,&v) ) return 1.0; t = P.DistanceTo(m_nurbs_surface->PointAt(s,v)); break; case distance_type: // confused user should be calling Value(double) return 1.0; // default must be one break; default: return 1.0; // default must be one } return Value(t); }
ON_BOOL32 ON_ArcCurve::SetEndPoint(ON_3dPoint end_point) { if (IsCircle()) return false; ON_BOOL32 rc = false; if ( m_dim == 3 || end_point.z == 0.0 ) { ON_3dPoint P; ON_3dVector T; double t = Domain()[0]; Ev1Der( t, P, T ); ON_Arc a; rc = a.Create( P, T, end_point ); if ( rc ) { m_arc = a; } else { ON_3dPoint start_point = PointAt(Domain()[0]); if (end_point.DistanceTo(start_point) < ON_ZERO_TOLERANCE*m_arc.Radius()){ //make arc into circle m_arc.plane.xaxis = start_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_LineCurve::Trim( const ON_Interval& domain ) { ON_BOOL32 rc = false; if ( domain.IsIncreasing() ) { ON_3dPoint p = PointAt( domain[0] ); ON_3dPoint q = PointAt( domain[1] ); if( p.DistanceTo(q)>0){ // 2 April 2003 Greg Arden A successfull trim // should return an IsValid ON_LineCurve . m_line.from = p; m_line.to = q; m_t = domain; rc = true; } } return rc; }
bool ON_Polyline::ClosestPointTo( const ON_3dPoint& point, double *t, int segment_index0, int segment_index1 ) const { bool rc = false; int segment_index; double segment_t, segment_d, best_t, best_d; best_t = 0.0; // to keep lint quiet best_d = 0.0; // to keep lint quiet if ( t ) { if ( segment_index0 < 0 ) segment_index0 = 0; if ( segment_index1 > SegmentCount() ) segment_index1 = SegmentCount(); for ( segment_index = segment_index0; segment_index < segment_index1; segment_index++ ) { double seg_length = m_a[segment_index].DistanceTo(m_a[segment_index + 1]); if (seg_length < ON_EPSILON) segment_t = 0.0; else { const ON_3dVector D = SegmentTangent(segment_index); const int i = ( point.DistanceTo(m_a[segment_index]) <= point.DistanceTo(m_a[segment_index+1]) ) ? 0 : 1; segment_t = (point - m_a[segment_index+i])*D/seg_length; if ( i ) { segment_t = 1.0 + segment_t; } if ( segment_t < 0.0 ) segment_t = 0.0; else if (segment_t > 1.0 ) segment_t = 1.0; } segment_d = point.DistanceTo((1-segment_t)*m_a[segment_index] + segment_t*m_a[segment_index+1]); if ( !rc || segment_d < best_d ) { best_t = segment_t + ((double)segment_index); best_d = segment_d; } rc = true; } } if (rc) *t = best_t; return rc; }
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; }
bool ON_PlaneSurface::GetClosestPoint( const ON_3dPoint& test_point, double* s,double* t, // parameters of local closest point returned here double maximum_distance, const ON_Interval* sdomain, // first parameter sub_domain const ON_Interval* tdomain // second parameter sub_domain ) const { double u = 0.0, v=0.0; ON_Interval sdom = Domain(0); ON_Interval tdom = Domain(1); if(sdomain==NULL) sdomain = &sdom; if(tdomain==NULL) tdomain = &tdom; bool rc = m_plane.ClosestPointTo( test_point, &u, &v ); if ( rc ) { // convert m_plane coordinates to ON_Surface coordinates if ( m_domain[0] != m_extents[0] ) { u = m_domain[0].ParameterAt( m_extents[0].NormalizedParameterAt(u) ); } if ( m_domain[1] != m_extents[1] ) { v = m_domain[1].ParameterAt( m_extents[1].NormalizedParameterAt(v) ); } if ( u < sdomain->Min() ) u = sdomain->Min(); else if ( u > sdomain->Max() ) u = sdomain->Max(); if ( v < tdomain->Min() ) v = tdomain->Min(); else if ( v > tdomain->Max() ) v = tdomain->Max(); if ( s ) *s = u; if ( t ) *t = v; if (maximum_distance > 0.0) { ON_3dPoint pt = PointAt(u,v); if ( test_point.DistanceTo(pt) > maximum_distance ) rc = false; } } return rc; }
static ON_NurbsSurface* ON_BrepExtrudeHelper_MakeConeSrf( const ON_3dPoint& apex_point, const ON_BrepEdge& edge, ON_BOOL32 bRev ) { // The "s" parameter runs along the edge. // The "t" parameter is the ruling parameter; // t=0 is at the base_edge and t=max is at the apex. // surface side location // south base_edge // east line from bRev?START:END of edge to apex // north singular side at apex // west line from bRev?END:START of edge to apex. ON_NurbsSurface* cone_srf = new ON_NurbsSurface(); if ( cone_srf->CreateConeSurface( apex_point, edge ) ) { if ( bRev ) cone_srf->Reverse(0); // get a decent interval for the ruling parameter double d = 0.0; ON_Interval edom = edge.Domain(); ON_3dPoint pt; int i, hint=0; for ( i = 0; i <= 16; i++ ) { if ( !edge.EvPoint( edom.ParameterAt(i/16.0), pt, 0, &hint ) ) continue; if ( pt.DistanceTo(apex_point) > d ) d = pt.DistanceTo(apex_point); } if ( d > ON_SQRT_EPSILON ) cone_srf->SetDomain(1,0.0,d); } else { delete cone_srf; cone_srf = 0; } return cone_srf; }
int CGetPolylinePoints::GetPoints() { m_point_array.Empty(); SetCommandPrompt( L"Start of polyline" ); AcceptNothing(); CRhinoGet::result res = GetPoint(); if( res == CRhinoGet::point ) { m_point_array.Append( Point() ); SetCommandPrompt( L"Next point of polyline" ); for( ;; ) { SetBasePoint( Point() ); res = GetPoint(); if( res == CRhinoGet::point ) { ON_3dPoint pt = Point(); if( pt.DistanceTo(m_point_array[m_point_array.Count()-1]) > ON_ZERO_TOLERANCE ) m_point_array.Append( Point() ); continue; } if( res == CRhinoGet::nothing ) break; return 0; } } return m_point_array.Count(); }
ON_BOOL32 ON_LineCurve::GetLocalClosestPoint( const ON_3dPoint& test_point, double seed_parameter, double* t, const ON_Interval* sub_domain ) const { if ( sub_domain ) { if ( seed_parameter < sub_domain->Min() ) seed_parameter = sub_domain->Min(); else if ( seed_parameter > sub_domain->Max() ) seed_parameter = sub_domain->Max(); } ON_BOOL32 rc = GetClosestPoint( test_point, t, 0.0, sub_domain ); if ( rc && t && seed_parameter != *t && test_point.DistanceTo(PointAt(seed_parameter)) <= test_point.DistanceTo(PointAt(*t)) ) { *t = seed_parameter; } return rc; }
bool ON_Localizer::CreateSphereLocalizer( ON_3dPoint P, double r0, double r1 ) { Destroy(); if ( P.IsValid() && ON_IsValid(r0) && ON_IsValid(r1) && r0 > 0.0 && r1 > 0.0 && r0 != r1 ) { m_P = P; m_V.Zero(); m_d.Set(r0,r1); m_type = sphere_type; } return (sphere_type == m_type); }
bool ON_GetClosestPointInPointList( int point_count, const ON_3dPoint* point_list, ON_3dPoint P, int* closest_point_index ) { bool rc = false; if ( point_count>0 && 0 != point_list && closest_point_index ) { double d = 1.0e300; double d2 = 1.0e300; double x,e; int i; int best_i = -1; //const double* pl = &point_list[0].x; for ( i = point_count; i--; point_list++ ) { e = d2; x = point_list->x - P.x; e = x*x; if ( e >= d2 ) continue; x = point_list->y - P.y; e += x*x; if ( e >= d2 ) continue; x = point_list->z - P.z; e += x*x; if ( e >= d2 ) continue; d2 = (1.0+ON_SQRT_EPSILON)*e; e = P.DistanceTo(*point_list); if ( e < d ) { d = e; best_i = point_count-i-1; } } if ( best_i >= 0 ) { if ( closest_point_index ) *closest_point_index = best_i; rc = true; } } return rc; }
static void DumpDistanceABHelper( ON_TextLog& text_log, ON_3dPoint A, ON_3dPoint B ) { const double tinyd = 1.0e-14; double d = A.DistanceTo(B); text_log.Print("distance A to B"); if ( !ON_IsValid(d) || d >= 1.0e-14 || d <= 0.0 ) { text_log.Print(" = "); } else { // This prevents diff from compaining about tiny changes. text_log.Print(" < "); d = tinyd; } text_log.Print(d); text_log.Print("\n"); }
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); }
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_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); }
bool ON_3dPointArray::GetClosestPoint( ON_3dPoint P, int* closest_point_index, double maximum_distance ) const { int i; bool rc = ON_GetClosestPointInPointList( m_count, m_a , P, &i ); if (rc) { if ( maximum_distance > 0.0 && P.DistanceTo(m_a[i]) > maximum_distance ) { rc = false; } else if ( closest_point_index ) { *closest_point_index = i; } } return rc; }
int ON_Intersect( // returns 0 = no intersections, // 1 = one intersection, // 2 = 2 intersections // 3 = line lies on cylinder // If 0 is returned, first point is point // on line closest to cylinder 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 cylinder. const ON_Line& line, const ON_Cylinder& cylinder, // if cylinder.height[0]==cylinder.height[1], // then infinite cyl is used. Otherwise // finite cyl is used. ON_3dPoint& A, ON_3dPoint& B // intersection point(s) returned here ) { ON_BOOL32 bFiniteCyl = true; int rc = 0; const double cylinder_radius = fabs(cylinder.circle.radius); double tol = cylinder_radius*ON_SQRT_EPSILON; if ( tol < ON_ZERO_TOLERANCE ) tol = ON_ZERO_TOLERANCE; ON_Line axis; axis.from = cylinder.circle.plane.origin + cylinder.height[0]*cylinder.circle.plane.zaxis; axis.to = cylinder.circle.plane.origin + cylinder.height[1]*cylinder.circle.plane.zaxis; if ( axis.Length() <= tol ) { axis.to = cylinder.circle.plane.origin + cylinder.circle.plane.zaxis; bFiniteCyl = false; } //ON_BOOL32 bIsParallel = false; double line_t, axis_t; if ( !ON_Intersect(line,axis,&line_t,&axis_t) ) { axis.ClosestPointTo( cylinder.circle.plane.origin, &axis_t ); line.ClosestPointTo( cylinder.circle.plane.origin, &line_t ); } ON_3dPoint line_point = line.PointAt(line_t); ON_3dPoint axis_point = axis.PointAt(axis_t); double d = line_point.DistanceTo(axis_point); if ( bFiniteCyl ) { if ( axis_t < 0.0 ) axis_t = 0.0; else if ( axis_t > 1.0 ) axis_t = 1.0; axis_point = axis.PointAt(axis_t); } if ( d >= cylinder_radius-tol) { rc = ( d <= cylinder_radius+tol ) ? 1 : 0; A = line_point; ON_3dVector V = line_point - axis_point; if ( bFiniteCyl ) { V = V - (V*cylinder.circle.plane.zaxis)*cylinder.circle.plane.zaxis; } V.Unitize(); B = axis_point + cylinder_radius*V; if ( rc == 1 ) { // check for overlap ON_3dPoint P = axis.ClosestPointTo(line.from); d = P.DistanceTo(line.from); if ( fabs(d-cylinder_radius) <= tol ) { P = axis.ClosestPointTo(line.to); d = P.DistanceTo(line.to); if ( fabs(d-cylinder_radius) <= tol ) { rc = 3; A = cylinder.ClosestPointTo(line.from); B = cylinder.ClosestPointTo(line.to); } } } } else { // transform to coordinate system where equation of cyl // is x^2 + y^2 = R^2 and solve for line parameter(s). ON_Xform xform; xform.Rotation( cylinder.circle.plane, ON_xy_plane ); ON_Line L = line; L.Transform(xform); const double x0 = L.from.x; const double x1 = L.to.x; const double x1mx0 = x1-x0; double ax = x1mx0*x1mx0; double bx = 2.0*x1mx0*x0; double cx = x0*x0; const double y0 = L.from.y; const double y1 = L.to.y; const double y1my0 = y1-y0; double ay = y1my0*y1my0; double by = 2.0*y1my0*y0; double cy = y0*y0; double t0, t1; int qerc = ON_SolveQuadraticEquation(ax+ay, bx+by, cx+cy-cylinder_radius*cylinder_radius, &t0,&t1); if ( qerc == 2 ) { // complex roots - ignore (tiny) imaginary part caused by computational noise. t1 = t0; } A = cylinder.ClosestPointTo(line.PointAt(t0)); B = cylinder.ClosestPointTo(line.PointAt(t1)); d = A.DistanceTo(B); if ( d <= ON_ZERO_TOLERANCE ) { A = line_point; ON_3dVector V = line_point - axis_point; if ( bFiniteCyl ) { V = V - (V*cylinder.circle.plane.zaxis)*cylinder.circle.plane.zaxis; } V.Unitize(); B = axis_point + cylinder_radius*V; rc = 1; } else rc = 2; } return rc; }
bool ON_Intersect( const ON_Line& lineA, const ON_Line& lineB, double* lineA_parameter, double* lineB_parameter ) { // If you are looking at this code because you don't like an // answer you are getting, then the first thing to try is // to read the header file comments and try calling // ON_IntersectLineLine. bool rc = false; double M_zero_tol = 0.0; int i, rank; double pr_tolerance, pivot, X[2], Y[2]; ON_3dVector A = lineA.Direction(); ON_3dVector B = lineB.Direction(); ON_3dVector C = lineB[0] - lineA[0]; ON_Matrix M(2,2); M[0][0] = ON_DotProduct( A, A ); M[1][1] = ON_DotProduct( B, B ); M[0][1] = M[1][0] = -ON_DotProduct( A, B ); // this swap done to get row+col pivot accuracy if ( M[0][0] < M[1][1] ) { M.SwapCols(0,1); i = 1; } else { i = 0; } pr_tolerance = fabs(M[1][1])*ON_SQRT_EPSILON; M_zero_tol = fabs(M[1][1])*ON_EPSILON; Y[0] = ON_DotProduct( A, C ); Y[1] = -ON_DotProduct( B, C ); rank = M.RowReduce( M_zero_tol, Y, &pivot ); if ( rank == 2 ) { // 19 November 2003 Dale Lear and Chuck // Added lineA.from/to == lineB.from/to tests // so exact answer gets returned when people // expect it. rc = true; if ( lineA.from == lineB.from ) { if ( lineA_parameter ) *lineA_parameter = 0.0; if ( lineB_parameter ) *lineB_parameter = 0.0; } else if ( lineA.from == lineB.to ) { if ( lineA_parameter ) *lineA_parameter = 0.0; if ( lineB_parameter ) *lineB_parameter = 1.0; } else if ( lineA.to == lineB.from ) { if ( lineA_parameter ) *lineA_parameter = 1.0; if ( lineB_parameter ) *lineB_parameter = 0.0; } else if ( lineA.to == lineB.to ) { if ( lineA_parameter ) *lineA_parameter = 1.0; if ( lineB_parameter ) *lineB_parameter = 1.0; } else { rc = M.BackSolve( 0.0, 2, Y, X ); if ( rc ) { if ( lineA_parameter ) *lineA_parameter = X[i]; if ( lineB_parameter ) *lineB_parameter = X[1-i]; if ( fabs(pivot) <= pr_tolerance ) { // test answer because matrix was close to singular // (This test is slow but it is rarely used.) ON_3dPoint pA = lineA.PointAt(X[i]); ON_3dPoint pB = lineB.PointAt(X[1-i]); double d = pA.DistanceTo(pB); if ( d > pr_tolerance && d > ON_ZERO_TOLERANCE ) { ON_3dPoint qA = lineA.ClosestPointTo(pB); ON_3dPoint qB = lineB.ClosestPointTo(pA); double dA = pA.DistanceTo(qB); double dB = pB.DistanceTo(qA); if ( 1.1*dA < d ) { rc = false; } else if ( 1.1*dB < d ) { rc = false; } } } } } } return rc; }
bool ON_BrepExtrude( ON_Brep& brep, const ON_Curve& path_curve, bool bCap ) { ON_Workspace ws; const int vcount0 = brep.m_V.Count(); const int tcount0 = brep.m_T.Count(); const int lcount0 = brep.m_L.Count(); const int ecount0 = brep.m_E.Count(); const int fcount0 = brep.m_F.Count(); const ON_3dPoint PathStart = path_curve.PointAtStart(); ON_3dPoint P = path_curve.PointAtEnd(); if ( !PathStart.IsValid() || !P.IsValid() ) return false; const ON_3dVector height = P - PathStart; if ( !height.IsValid() || height.Length() <= ON_ZERO_TOLERANCE ) return false; ON_Xform tr; tr.Translation(height); // count number of new sides int side_count = 0; int i, vi, ei, fi; bool* bSideEdge = (bool*)ws.GetIntMemory(ecount0*sizeof(bSideEdge[0])); for ( ei = 0; ei < ecount0; ei++ ) { const ON_BrepEdge& e = brep.m_E[ei]; if ( 1 == e.m_ti.Count() ) { side_count++; bSideEdge[ei] = true; } else { bSideEdge[ei] = false; } } brep.m_V.Reserve( 2*vcount0 ); i = 4*side_count + (bCap?tcount0:0); brep.m_T.Reserve( tcount0 + i ); brep.m_C2.Reserve( brep.m_C2.Count() + i ); brep.m_L.Reserve( lcount0 + side_count + (bCap?lcount0:0) ); i = side_count + (bCap?ecount0:side_count); brep.m_E.Reserve( ecount0 + i ); brep.m_C3.Reserve( brep.m_C3.Count() + i ); i = side_count + (bCap?fcount0:0); brep.m_F.Reserve( fcount0 + i ); brep.m_S.Reserve( brep.m_S.Count() + i ); bool bOK = true; // build top vertices int* topvimap = ws.GetIntMemory(vcount0); memset(topvimap,0,vcount0*sizeof(topvimap[0])); if ( bCap ) { for ( vi = 0; vi < vcount0; vi++ ) { const ON_BrepVertex& bottomv = brep.m_V[vi]; ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance); topvimap[vi] = topv.m_vertex_index; } } else { for ( ei = 0; ei < ecount0; ei++ ) { if ( bSideEdge[ei] ) { const ON_BrepEdge& bottome = brep.m_E[ei]; int bottomvi0 = bottome.m_vi[0]; if ( bottomvi0 < 0 || bottomvi0 >= vcount0 ) { bOK = false; break; } int bottomvi1 = bottome.m_vi[1]; if ( bottomvi1 < 0 || bottomvi1 >= vcount0 ) { bOK = false; break; } if ( !topvimap[bottomvi0] ) { const ON_BrepVertex& bottomv = brep.m_V[bottomvi0]; ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance); topvimap[bottomvi0] = topv.m_vertex_index; } if ( !topvimap[bottomvi1] ) { const ON_BrepVertex& bottomv = brep.m_V[bottomvi1]; ON_BrepVertex& topv = brep.NewVertex(bottomv.point+height,bottomv.m_tolerance); topvimap[bottomvi1] = topv.m_vertex_index; } } } } // build top edges int* topeimap = ws.GetIntMemory(ecount0); memset(topeimap,0,ecount0*sizeof(topeimap[0])); if ( bOK ) for ( ei = 0; ei < ecount0; ei++ ) { if ( bCap || bSideEdge[ei] ) { const ON_BrepEdge& bottome = brep.m_E[ei]; ON_BrepVertex& topv0 = brep.m_V[topvimap[bottome.m_vi[0]]]; ON_BrepVertex& topv1 = brep.m_V[topvimap[bottome.m_vi[1]]]; ON_Curve* c3 = bottome.DuplicateCurve(); if ( !c3 ) { bOK = false; break; } c3->Transform(tr); int c3i = brep.AddEdgeCurve(c3); ON_BrepEdge& tope = brep.NewEdge(topv0,topv1,c3i,0,bottome.m_tolerance); topeimap[ei] = tope.m_edge_index; } } // build side edges int* sideveimap = ws.GetIntMemory(vcount0); memset(sideveimap,0,vcount0*sizeof(sideveimap[0])); if ( bOK ) for ( vi = 0; vi < vcount0; vi++ ) { ON_BrepVertex& bottomv = brep.m_V[vi]; for ( int vei = 0; vei < bottomv.m_ei.Count(); vei++ ) { if ( bSideEdge[bottomv.m_ei[vei]] && topvimap[vi] ) { ON_BrepVertex& topv = brep.m_V[topvimap[vi]]; ON_Curve* c3 = path_curve.DuplicateCurve(); if ( !c3 ) { bOK = false; } else { ON_3dVector D = bottomv.point - PathStart; c3->Translate(D); int c3i = brep.AddEdgeCurve(c3); const ON_BrepEdge& e = brep.NewEdge(bottomv,topv,c3i,0,0.0); sideveimap[vi] = e.m_edge_index; } break; } } } if ( bOK && bCap ) { // build top faces for (fi = 0; fi < fcount0; fi++ ) { const ON_BrepFace& bottomf = brep.m_F[fi]; ON_Surface* srf = bottomf.DuplicateSurface(); if ( !srf ) { bOK = false; break; } srf->Transform(tr); int si = brep.AddSurface(srf); ON_BrepFace& topf = brep.NewFace(si); topf.m_bRev = !bottomf.m_bRev; const int loop_count = bottomf.m_li.Count(); topf.m_li.Reserve(loop_count); for ( int fli = 0; fli < loop_count; fli++ ) { const ON_BrepLoop& bottoml = brep.m_L[bottomf.m_li[fli]]; ON_BrepLoop& topl = brep.NewLoop(bottoml.m_type,topf); const int loop_trim_count = bottoml.m_ti.Count(); topl.m_ti.Reserve(loop_trim_count); for ( int lti = 0; lti < loop_trim_count; lti++ ) { const ON_BrepTrim& bottomt = brep.m_T[bottoml.m_ti[lti]]; ON_NurbsCurve* c2 = ON_NurbsCurve::New(); if ( !bottomt.GetNurbForm(*c2) ) { delete c2; bOK = false; break; } int c2i = brep.AddTrimCurve(c2); ON_BrepTrim* topt = 0; if ( bottomt.m_ei >= 0 ) { ON_BrepEdge& tope = brep.m_E[topeimap[bottomt.m_ei]]; topt = &brep.NewTrim(tope,bottomt.m_bRev3d,topl,c2i); } else { // singular trim ON_BrepVertex& topv = brep.m_V[topvimap[bottomt.m_vi[0]]]; topt = &brep.NewSingularTrim(topv,topl,bottomt.m_iso,c2i); } topt->m_tolerance[0] = bottomt.m_tolerance[0]; topt->m_tolerance[1] = bottomt.m_tolerance[1]; topt->m_pbox = bottomt.m_pbox; topt->m_type = bottomt.m_type; topt->m_iso = bottomt.m_iso; } topl.m_pbox = bottoml.m_pbox; } } } // build sides int bRev3d[4] = {0,0,1,1}; int vid[4], eid[4]; if( bOK ) for ( ei = 0; ei < ecount0; ei++ ) { if ( bSideEdge[ei] && topeimap[ei] ) { ON_BrepEdge& bottome = brep.m_E[ei]; ON_BrepEdge& tope = brep.m_E[topeimap[ei]]; vid[0] = bottome.m_vi[0]; vid[1] = bottome.m_vi[1]; vid[2] = topvimap[vid[1]]; vid[3] = topvimap[vid[0]]; if ( sideveimap[vid[0]] && sideveimap[vid[1]] ) { ON_BrepEdge& leftedge = brep.m_E[sideveimap[vid[0]]]; ON_BrepEdge& rightedge = brep.m_E[sideveimap[vid[1]]]; ON_Curve* cx = bottome.DuplicateCurve(); if ( !cx ) { bOK = false; break; } ON_Curve* cy = leftedge.DuplicateCurve(); if ( !cy ) { delete cx; bOK = false; break; } ON_SumSurface* srf = new ON_SumSurface(); srf->m_curve[0] = cx; srf->m_curve[1] = cy; srf->m_basepoint = srf->m_curve[1]->PointAtStart(); srf->m_basepoint.x = -srf->m_basepoint.x; srf->m_basepoint.y = -srf->m_basepoint.y; srf->m_basepoint.z = -srf->m_basepoint.z; eid[0] = bottome.m_edge_index; eid[1] = rightedge.m_edge_index; eid[2] = tope.m_edge_index; eid[3] = leftedge.m_edge_index; ON_BrepFace* face = brep.NewFace(srf,vid,eid,bRev3d); if ( !face ) { bOK = false; break; } else if ( bottome.m_ti.Count() == 2 ) { const ON_BrepTrim& trim0 = brep.m_T[bottome.m_ti[0]]; const ON_BrepTrim& trim1 = brep.m_T[bottome.m_ti[1]]; const ON_BrepLoop& loop0 = brep.m_L[trim0.m_li]; const ON_BrepLoop& loop1 = brep.m_L[trim1.m_li]; bool bBottomFaceRev = brep.m_F[(loop0.m_fi != face->m_face_index) ? loop0.m_fi : loop1.m_fi].m_bRev; bool bSideFaceRev = ( trim0.m_bRev3d != trim1.m_bRev3d ) ? bBottomFaceRev : !bBottomFaceRev; face->m_bRev = bSideFaceRev; } } } } if ( !bOK ) { for ( vi = brep.m_V.Count(); vi >= vcount0; vi-- ) { brep.DeleteVertex(brep.m_V[vi]); } } return bOK; }
double ON_Line::DistanceTo( ON_3dPoint test_point ) const { return test_point.DistanceTo(ClosestPointTo(test_point)); }
bool ON_Mesh::EvaluatePoint( const class ON_ObjRef& objref, ON_3dPoint& P ) const { // virtual function default P = ON_UNSET_POINT; ON_COMPONENT_INDEX ci = objref.m_component_index; switch ( ci.m_type ) { case ON_COMPONENT_INDEX::mesh_vertex: if ( ci.m_index >= 0 && ci.m_index < m_V.Count() ) P = m_V[ci.m_index]; break; case ON_COMPONENT_INDEX::meshtop_vertex: if ( ci.m_index >= 0 && ci.m_index < m_top.m_topv.Count() ) { const ON_MeshTopologyVertex& topv = m_top.m_topv[ci.m_index]; if ( topv.m_v_count > 0 && topv.m_vi ) { int vi = topv.m_vi[0]; if ( vi >= 0 && vi < m_V.Count() ) P = m_V[vi]; } } break; case ON_COMPONENT_INDEX::meshtop_edge: if ( 5 == objref.m_evp.m_t_type && fabs(objref.m_evp.m_t[0] + objref.m_evp.m_t[1] - 1.0) <= ON_SQRT_EPSILON ) { ON_Line L = m_top.TopEdgeLine(ci.m_index); if ( L.IsValid() ) { P = L.PointAt(objref.m_evp.m_t[0]); } } break; case ON_COMPONENT_INDEX::mesh_face: if ( 4 == objref.m_evp.m_t_type && fabs(objref.m_evp.m_t[0] + objref.m_evp.m_t[1] + objref.m_evp.m_t[2] + objref.m_evp.m_t[3] - 1.0) <= ON_SQRT_EPSILON ) { if ( ci.m_index >= 0 && ci.m_index < m_F.Count() ) { const int* fvi = m_F[ci.m_index].vi; if ( fvi[0] < 0 || fvi[0] >= m_V.Count() ) break; if ( fvi[1] < 0 || fvi[1] >= m_V.Count() ) break; if ( fvi[2] < 0 || fvi[2] >= m_V.Count() ) break; if ( fvi[3] < 0 || fvi[3] >= m_V.Count() ) break; ON_3dPoint V[4]; V[0] = m_V[fvi[0]]; V[1] = m_V[fvi[1]]; V[2] = m_V[fvi[2]]; V[3] = m_V[fvi[3]]; P = objref.m_evp.m_t[0]*V[0] + objref.m_evp.m_t[1]*V[1] + objref.m_evp.m_t[2]*V[2] + objref.m_evp.m_t[3]*V[3]; } } break; default: // intentionally skipping other ON_COMPONENT_INDEX::TYPE enum values break; } return P.IsValid(); }
extern "C" void rt_revolve_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol) { struct rt_db_internal *tmp_internal; struct rt_revolve_internal *rip; struct rt_sketch_internal *eip; BU_ALLOC(tmp_internal, struct rt_db_internal); RT_DB_INTERNAL_INIT(tmp_internal); rip = (struct rt_revolve_internal *)ip->idb_ptr; RT_REVOLVE_CK_MAGIC(rip); eip = rip->skt; RT_SKETCH_CK_MAGIC(eip); ON_3dPoint plane_origin; ON_3dVector plane_x_dir, plane_y_dir; bool full_revolve = true; if (rip->ang < 2*ON_PI && rip->ang > 0) full_revolve = false; // Find plane in 3 space corresponding to the sketch. vect_t startpoint; VADD2(startpoint, rip->v3d, rip->r); plane_origin = ON_3dPoint(startpoint); plane_x_dir = ON_3dVector(eip->u_vec); plane_y_dir = ON_3dVector(eip->v_vec); const ON_Plane sketch_plane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir); // For the brep, need the list of 3D vertex points. In sketch, they // are stored as 2D coordinates, so use the sketch_plane to define 3 space // points for the vertices. for (size_t i = 0; i < eip->vert_count; i++) { (*b)->NewVertex(sketch_plane.PointAt(eip->verts[i][0], eip->verts[i][1]), 0.0); } // Create the brep elements corresponding to the sketch lines, curves // and bezier segments. Create 2d, 3d and BrepEdge elements for each segment. // Will need to use the bboxes of each element to // build the overall bounding box for the face. Use bGrowBox to expand // a single box. struct line_seg *lsg; struct carc_seg *csg; struct bezier_seg *bsg; uint32_t *lng; for (size_t i = 0; i < (&eip->curve)->count; i++) { lng = (uint32_t *)(&eip->curve)->segment[i]; switch (*lng) { case CURVE_LSEG_MAGIC: { lsg = (struct line_seg *)lng; ON_Curve* lsg3d = new ON_LineCurve((*b)->m_V[lsg->start].Point(), (*b)->m_V[lsg->end].Point()); lsg3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(lsg3d); } break; case CURVE_CARC_MAGIC: csg = (struct carc_seg *)lng; if (csg->radius < 0) { { ON_3dPoint cntrpt = (*b)->m_V[csg->end].Point(); ON_3dPoint edgept = (*b)->m_V[csg->start].Point(); ON_Plane cplane = ON_Plane(cntrpt, plane_x_dir, plane_y_dir); ON_Circle c3dcirc = ON_Circle(cplane, cntrpt.DistanceTo(edgept)); ON_Curve* c3d = new ON_ArcCurve((const ON_Circle)c3dcirc); c3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(c3d); } } else { // need to calculated 3rd point on arc - look to sketch.c around line 581 for // logic } break; case CURVE_BEZIER_MAGIC: bsg = (struct bezier_seg *)lng; { ON_3dPointArray bezpoints = ON_3dPointArray(bsg->degree + 1); for (int j = 0; j < bsg->degree + 1; j++) { bezpoints.Append((*b)->m_V[bsg->ctl_points[j]].Point()); } ON_BezierCurve bez3d = ON_BezierCurve((const ON_3dPointArray)bezpoints); ON_NurbsCurve* beznurb3d = ON_NurbsCurve::New(); bez3d.GetNurbForm(*beznurb3d); beznurb3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(beznurb3d); } break; default: bu_log("Unhandled sketch object\n"); break; } } vect_t endpoint; VADD2(endpoint, rip->v3d, rip->axis3d); const ON_Line& revaxis = ON_Line(ON_3dPoint(rip->v3d), ON_3dPoint(endpoint)); FindLoops(b, &revaxis, rip->ang); // Create the two boundary surfaces, if it's not a full revolution if (!full_revolve) { // First, deduce the transformation matrices to calculate the position of the end surface // The transformation matrices are to rotate an arbitrary point around an arbitrary axis // Let the point A = (x, y, z), the rotation axis is p1p2 = (x2,y2,z2)-(x1,y1,z1) = (a,b,c) // Then T1 is to translate p1 to the origin // Rx is to rotate p1p2 around the X axis to the plane XOZ // Ry is to rotate p1p2 around the Y axis to be coincident to Z axis // Rz is to rotate A with the angle around Z axis (the new p1p2) // RxInv, RyInv, T1Inv are the inverse transformation of Rx, Ry, T1, respectively. // The whole transformation is A' = A*T1*Rx*Ry*Rz*Ry*Inv*Rx*Inv = A*R vect_t end_plane_origin, end_plane_x_dir, end_plane_y_dir; mat_t R; MAT_IDN(R); mat_t T1, Rx, Ry, Rz, RxInv, RyInv, T1Inv; MAT_IDN(T1); VSET(&T1[12], -rip->v3d[0], -rip->v3d[1], -rip->v3d[2]); MAT_IDN(Rx); fastf_t v = sqrt(rip->axis3d[1]*rip->axis3d[1]+rip->axis3d[2]*rip->axis3d[2]); VSET(&Rx[4], 0, rip->axis3d[2]/v, rip->axis3d[1]/v); VSET(&Rx[8], 0, -rip->axis3d[1]/v, rip->axis3d[2]/v); MAT_IDN(Ry); fastf_t u = MAGNITUDE(rip->axis3d); VSET(&Ry[0], v/u, 0, -rip->axis3d[0]/u); VSET(&Ry[8], rip->axis3d[0]/u, 0, v/u); MAT_IDN(Rz); fastf_t C, S; C = cos(rip->ang); S = sin(rip->ang); VSET(&Rz[0], C, S, 0); VSET(&Rz[4], -S, C, 0); bn_mat_inv(RxInv, Rx); bn_mat_inv(RyInv, Ry); bn_mat_inv(T1Inv, T1); mat_t temp; bn_mat_mul4(temp, T1, Rx, Ry, Rz); bn_mat_mul4(R, temp, RyInv, RxInv, T1Inv); VEC3X3MAT(end_plane_origin, plane_origin, R); VADD2(end_plane_origin, end_plane_origin, &R[12]); VEC3X3MAT(end_plane_x_dir, plane_x_dir, R); VEC3X3MAT(end_plane_y_dir, plane_y_dir, R); // Create the start and end surface with rt_sketch_brep() struct rt_sketch_internal sketch; sketch = *(rip->skt); ON_Brep *b1 = ON_Brep::New(); VMOVE(sketch.V, plane_origin); VMOVE(sketch.u_vec, plane_x_dir); VMOVE(sketch.v_vec, plane_y_dir); tmp_internal->idb_ptr = (void *)(&sketch); rt_sketch_brep(&b1, tmp_internal, tol); (*b)->Append(*b1->Duplicate()); ON_Brep *b2 = ON_Brep::New(); VMOVE(sketch.V, end_plane_origin); VMOVE(sketch.u_vec, end_plane_x_dir); VMOVE(sketch.v_vec, end_plane_y_dir); tmp_internal->idb_ptr = (void *)(&sketch); rt_sketch_brep(&b2, tmp_internal, tol); (*b)->Append(*b2->Duplicate()); (*b)->FlipFace((*b)->m_F[(*b)->m_F.Count()-1]); } bu_free(tmp_internal, "free temporary rt_db_internal"); }
int ON_ArePointsOnPlane( // returns 0=no, 1 = yes, 2 = pointset is (to tolerance) a single point on the line int dim, // 2 or 3 int is_rat, int count, int stride, const double* point, const ON_BoundingBox& bbox, // if needed, use ON_GetBoundingBox(dim,is_rat,count,stride,point) const ON_Plane& plane, // line to test double tolerance ) { double w; int i, j, k; if ( count < 1 ) return 0; if ( !plane.IsValid() ) { ON_ERROR("plane parameter is not valid"); return 0; } if ( !bbox.IsValid() ) { ON_ERROR("bbox parameter is not valid"); return 0; } if ( !ON_IsValid(tolerance) || tolerance < 0.0 ) { ON_ERROR("tolerance must be >= 0.0"); return 0; } if ( dim < 2 || dim > 3 ) { ON_ERROR("dim must be 2 or 3"); return 0; } if ( stride < (is_rat?(dim+1):dim) ) { ON_ERROR("stride parameter is too small"); return 0; } if ( 0 == point ) { ON_ERROR("point parameter is null"); return 0; } int rc = 0; if ( tolerance == 0.0 ) { tolerance = bbox.Tolerance(); } ON_3dPoint Q; // test bounding box to quickly detect the common coordinate axis cases rc = (count == 1 || bbox.Diagonal().Length() <= tolerance) ? 2 : 1; for ( i = 0; rc && i < 2; i++ ) { Q.x = bbox[i].x; for ( j = 0; rc && j < 2; j++) { Q.y = bbox[j].y; for ( k = 0; rc && k < 2; k++) { Q.z = bbox[k].z; if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance ) rc = 0; } } } if ( !rc ) { // test points one by one Q.Zero(); rc = (count == 1 || bbox.Diagonal().Length() <= tolerance) ? 2 : 1; if ( is_rat ) { for ( i = 0; i < count; i++ ) { w = point[dim]; if ( w == 0.0 ) { ON_ERROR("rational point has zero weight"); return 0; } ON_ArrayScale( dim, 1.0/w, point, &Q.x ); if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance ) { rc = 0; break; } point += stride; } } else { for ( i = 0; i < count; i++ ) { memcpy( &Q.x, point, dim*sizeof(Q.x) ); if ( Q.DistanceTo( plane.ClosestPointTo( Q ) ) > tolerance ) { rc = 0; break; } point += stride; } } } return rc; }
extern "C" void rt_sketch_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *UNUSED(tol)) { struct rt_sketch_internal *eip; RT_CK_DB_INTERNAL(ip); eip = (struct rt_sketch_internal *)ip->idb_ptr; RT_SKETCH_CK_MAGIC(eip); ON_3dPoint plane_origin; ON_3dVector plane_x_dir, plane_y_dir; // Find plane in 3 space corresponding to the sketch. plane_origin = ON_3dPoint(eip->V); plane_x_dir = ON_3dVector(eip->u_vec); plane_y_dir = ON_3dVector(eip->v_vec); const ON_Plane sketch_plane = ON_Plane(plane_origin, plane_x_dir, plane_y_dir); // For the brep, need the list of 3D vertex points. In sketch, they // are stored as 2D coordinates, so use the sketch_plane to define 3 space // points for the vertices. for (size_t i = 0; i < eip->vert_count; i++) { (*b)->NewVertex(sketch_plane.PointAt(eip->verts[i][0], eip->verts[i][1]), 0.0); } // Create the brep elements corresponding to the sketch lines, curves // and bezier segments. Create 2d, 3d and BrepEdge elements for each segment. // Will need to use the bboxes of each element to // build the overall bounding box for the face. Use bGrowBox to expand // a single box. struct line_seg *lsg; struct carc_seg *csg; struct bezier_seg *bsg; uint32_t *lng; for (size_t i = 0; i < (&eip->curve)->count; i++) { lng = (uint32_t *)(&eip->curve)->segment[i]; switch (*lng) { case CURVE_LSEG_MAGIC: { lsg = (struct line_seg *)lng; ON_Curve* lsg3d = new ON_LineCurve((*b)->m_V[lsg->start].Point(), (*b)->m_V[lsg->end].Point()); lsg3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(lsg3d); } break; case CURVE_CARC_MAGIC: csg = (struct carc_seg *)lng; if (csg->radius < 0) { ON_3dPoint cntrpt = (*b)->m_V[csg->end].Point(); ON_3dPoint edgept = (*b)->m_V[csg->start].Point(); ON_Plane cplane = ON_Plane(cntrpt, plane_x_dir, plane_y_dir); ON_Circle c3dcirc = ON_Circle(cplane, cntrpt.DistanceTo(edgept)); ON_Curve* c3d = new ON_ArcCurve((const ON_Circle)c3dcirc); c3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(c3d); } else { // need to calculated 3rd point on arc - look to sketch.c around line 581 for // logic } break; case CURVE_BEZIER_MAGIC: bsg = (struct bezier_seg *)lng; { ON_3dPointArray bezpoints(bsg->degree + 1); for (int j = 0; j < bsg->degree + 1; j++) { bezpoints.Append((*b)->m_V[bsg->ctl_points[j]].Point()); } ON_BezierCurve bez3d = ON_BezierCurve((const ON_3dPointArray)bezpoints); ON_NurbsCurve* beznurb3d = ON_NurbsCurve::New(); bez3d.GetNurbForm(*beznurb3d); beznurb3d->SetDomain(0.0, 1.0); (*b)->m_C3.Append(beznurb3d); } break; default: bu_log("Unhandled sketch object\n"); break; } } // Create the plane surface and brep face. ON_PlaneSurface *sketch_surf = new ON_PlaneSurface(sketch_plane); (*b)->m_S.Append(sketch_surf); int surfindex = (*b)->m_S.Count(); ON_BrepFace& face = (*b)->NewFace(surfindex - 1); // For the purposes of BREP creation, it is necessary to identify // loops created by sketch segments. This information is not stored // in the sketch data structures themselves, and thus must be deduced FindLoops(b); const ON_BrepLoop* tloop = (*b)->m_L.First(); sketch_surf->SetDomain(0, tloop->m_pbox.m_min.x, tloop->m_pbox.m_max.x); sketch_surf->SetDomain(1, tloop->m_pbox.m_min.y, tloop->m_pbox.m_max.y); sketch_surf->SetExtents(0, sketch_surf->Domain(0)); sketch_surf->SetExtents(1, sketch_surf->Domain(1)); (*b)->SetTrimIsoFlags(face); (*b)->FlipFace(face); (*b)->Compact(); }