RH_C_FUNCTION void ON_Brep_DuplicateEdgeCurves(const ON_Brep* pBrep, ON_SimpleArray<ON_Curve*>* pOutCurves, bool nakedOnly) { if (pBrep && pOutCurves) { for(int i = 0; i < pBrep->m_E.Count(); i++) { const ON_BrepEdge& edge = pBrep->m_E[i]; if( nakedOnly && edge.m_ti.Count()!=1 ) continue; ON_Curve* curve = edge.DuplicateCurve(); if(curve) { // From RhinoScript: // make the curve direction go in the natural boundary loop direction // so that the curve directions come out consistantly if( pBrep->m_T[edge.m_ti[0]].m_bRev3d ) curve->Reverse(); if( pBrep->m_T[edge.m_ti[0]].Face()->m_bRev ) curve->Reverse(); pOutCurves->Append(curve); } } } }
ON_Curve* ON_SurfaceProxy::Pushup( const ON_Curve& curve_2d, double tolerance, const ON_Interval* curve_2d_subdomain ) const { ON_Curve* pushupcurve = 0; if ( 0 != m_surface ) { if ( m_bTransposed ) { ON_Curve* transposedcurve = curve_2d.DuplicateCurve(); if ( 0 != transposedcurve ) { transposedcurve->SwapCoordinates(0,1); pushupcurve = m_surface->Pushup( *transposedcurve, tolerance, curve_2d_subdomain ); delete transposedcurve; transposedcurve = 0; } } else { pushupcurve = m_surface->Pushup( curve_2d, tolerance, curve_2d_subdomain ); } } return pushupcurve; }
BOOL COrientOnCrvXform::CalculateTransform( CRhinoViewport& vp, const ON_3dPoint& pt, ON_Xform& xform ) { BOOL bResult = FALSE; if( m_path_curve ) { double t = 0.0; if( m_path_curve->GetClosestPoint(pt, &t) ) { ON_3dPoint origin = m_path_curve->PointAt( t ); ON_Plane dest_plane; if( m_perp_mode ) { ON_3dVector tangent = m_path_curve->TangentAt( t ); MakeNormalPlane( origin, tangent, dest_plane ); } else { dest_plane.origin = origin; dest_plane.xaxis = m_path_curve->TangentAt( t ); dest_plane.zaxis = m_base_plane.zaxis; dest_plane.yaxis = ON_CrossProduct( dest_plane.zaxis, dest_plane.xaxis ); dest_plane.UpdateEquation(); } xform.Rotation( m_base_plane, dest_plane ); bResult = xform.IsValid() ? TRUE : FALSE; } } return bResult; }
static void UnrotateHatch(ON_Hatch* hatch) { double a = arbaxisRotation(hatch->Plane()); ON_Plane& plane = *(ON_Plane*)(&hatch->Plane()); if(fabs(a) > ON_ZERO_TOLERANCE) { plane.Rotate(-a, plane.zaxis); for(int i = 0; i < hatch->LoopCount(); i++) { ON_Curve* pC = (ON_Curve*)hatch->Loop(i)->Curve(); pC->Rotate(a, ON_zaxis, ON_origin); } hatch->SetPatternRotation(hatch->PatternRotation()+a); } ON_3dPoint P; plane.ClosestPointTo(ON_origin, &P.x, &P.y); if(fabs(P.x) > ON_ZERO_TOLERANCE ||fabs(P.y) > ON_ZERO_TOLERANCE ||fabs(P.z) > ON_ZERO_TOLERANCE) { ON_2dVector V(-P.x, -P.y); for(int i = 0; i < hatch->LoopCount(); i++) { ON_Curve* pC = (ON_Curve*)hatch->Loop(i)->Curve(); pC->Translate(V); } P = plane.PointAt(P.x, P.y); plane.origin = P; } }
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 ); }
RH_C_FUNCTION ON_MassProperties* ON_Hatch_AreaMassProperties(const ON_Hatch* pConstHatch, double rel_tol, double abs_tol) { ON_MassProperties* rc = NULL; if( pConstHatch ) { ON_BoundingBox bbox = pConstHatch->BoundingBox(); ON_3dPoint basepoint = bbox.Center(); basepoint = pConstHatch->Plane().ClosestPointTo(basepoint); ON_ClassArray<ON_MassProperties> list; for( int i=0; i<pConstHatch->LoopCount(); i++ ) { const ON_HatchLoop* pLoop = pConstHatch->Loop(i); if( NULL==pLoop ) continue; ON_Curve* pCurve = pConstHatch->LoopCurve3d(i); if( NULL==pCurve ) continue; ON_MassProperties mp; if( pCurve->AreaMassProperties(basepoint, pConstHatch->Plane().Normal(), mp, true, true, true, true, rel_tol, abs_tol) ) { mp.m_mass = fabs(mp.m_mass); if( pLoop->Type() == ON_HatchLoop::ltInner ) mp.m_mass = -mp.m_mass; list.Append(mp); } delete pCurve; } if( list.Count()==1 ) { rc = new ON_MassProperties(); *rc = list[0]; } else if( list.Count()>1 ) { int count = list.Count(); const ON_MassProperties* pieces = list.Array(); rc = new ON_MassProperties(); if( !rc->Sum(count, pieces) ) { delete rc; rc = NULL; } } } return rc; }
bool ON_HatchLoop::SetCurve( const ON_Curve& curve) { ON_Curve* pC = curve.DuplicateCurve(); if( pC) { if(pC->Dimension() == 3 && !pC->ChangeDimension(2)) return false; if( m_p2dCurve) delete m_p2dCurve; m_p2dCurve = pC; } return true; }
ON_Surface::ISO ON_SurfaceProxy::IsIsoparametric( // returns isoparametric status of 2d curve const ON_Curve& crv, const ON_Interval* subdomain ) const { // this is a virtual overide of an ON_Surface::IsIsoparametric const ON_Curve* pC = &crv; ON_Curve* pTranC = NULL; if(m_bTransposed) { pTranC = crv.DuplicateCurve(); pTranC->SwapCoordinates(0,1); pC = pTranC; } ON_Surface::ISO iso = m_surface->IsIsoparametric( *pC, subdomain); if (pTranC) { switch(iso) { case x_iso: iso = y_iso; break; case y_iso: iso = x_iso; break; case W_iso: iso = S_iso; break; case S_iso: iso = W_iso; break; case N_iso: iso = E_iso; break; case E_iso: iso = N_iso; break; default: // intentionally ignoring other ON_Surface::ISO enum values break; } delete pTranC; } return iso; }
BOOL ON_Hatch::GetBBox( double* bmin, double* bmax, BOOL bGrowBox) const { int i; int count = m_loops.Count(); BOOL rc = true; ON_Curve* pC; for( i = 0; rc && i < count; i++) { pC = LoopCurve3d( i); if( pC) { rc = pC->GetBBox( bmin, bmax, i?true:bGrowBox); delete pC; } } return rc; }
void ON_CurveProxy::DestroyRuntimeCache( bool bDelete ) { if ( m_ctree ) { #if defined(OPENNURBS_PLUS_INC_) if ( bDelete ) delete m_ctree; #endif m_ctree = 0; } if ( 0 != m_real_curve && m_real_curve != this ) { ON_Curve* curve = const_cast<ON_Curve*>(m_real_curve); if ( 0 != curve ) curve->DestroyRuntimeCache( bDelete ); } }
ON_Curve* ON_SurfaceProxy::Pullback( const ON_Curve& curve_3d, double tolerance, const ON_Interval* curve_3d_subdomain, ON_3dPoint start_uv, ON_3dPoint end_uv ) const { ON_Curve* pullbackcurve = 0; if ( 0 != m_surface ) { pullbackcurve = m_surface->Pullback( curve_3d, tolerance, curve_3d_subdomain, start_uv, end_uv ); if ( m_bTransposed && 0 != pullbackcurve ) { pullbackcurve->SwapCoordinates(0,1); } } return pullbackcurve; }
bool ON_HatchLoop::SetCurve( const ON_Curve& curve) { ON_Curve* pC = curve.DuplicateCurve(); if( pC) { if( m_p2dCurve) delete m_p2dCurve; m_p2dCurve = pC; } return true; }
// Copy the 2d curve, make it 3d, and transform it // to the 3d plane position ON_Curve* ON_Hatch::LoopCurve3d( int index) const { int count = m_loops.Count(); ON_Curve* pC = NULL; if( index >= 0 && index < count) { if( m_loops[index]->Curve()) { pC = m_loops[index]->Curve()->DuplicateCurve(); if( pC) { pC->ChangeDimension( 3); ON_Xform xf; xf.Rotation( ON_xy_plane, m_plane); pC->Transform( xf); } } } return pC; }
RH_C_FUNCTION ON_Curve* ON_Curve_TrimExtend( const ON_Curve* pCurve, double t0, double t1, bool trimming) { ON_Curve* rc = NULL; if( pCurve ) { if( trimming ) { rc = ::ON_TrimCurve(*pCurve, ON_Interval(t0,t1)); } else { ON_Curve* pNewCurve = pCurve->DuplicateCurve(); if( pNewCurve ) { if( pNewCurve->Extend(ON_Interval(t0,t1)) ) rc = pNewCurve; else delete pNewCurve; } } } return rc; }
RH_C_FUNCTION void ON_Brep_DuplicateEdgeCurves(const ON_Brep* pConstBrep, ON_SimpleArray<ON_Curve*>* pOutCurves, bool nakedOnly, bool nakedOuter, bool nakedInner) { if (pConstBrep && pOutCurves) { for(int i = 0; i < pConstBrep->m_E.Count(); i++) { const ON_BrepEdge& edge = pConstBrep->m_E[i]; if( nakedOnly ) { if( edge.m_ti.Count() != 1 ) continue; const ON_BrepTrim& trim = pConstBrep->m_T[edge.m_ti[0]]; const ON_BrepLoop& loop = pConstBrep->m_L[trim.m_li]; bool acceptable = (nakedOuter && loop.m_type == ON_BrepLoop::outer) || (nakedInner && loop.m_type == ON_BrepLoop::inner); if( !acceptable ) continue; } ON_Curve* curve = edge.DuplicateCurve(); if(curve) { // From RhinoScript: // make the curve direction go in the natural boundary loop direction // so that the curve directions come out consistantly if( pConstBrep->m_T[edge.m_ti[0]].m_bRev3d ) curve->Reverse(); if( pConstBrep->m_T[edge.m_ti[0]].Face()->m_bRev ) curve->Reverse(); pOutCurves->Append(curve); } } } }
// Add a curve to the partial boundingbox result. static void ON_Brep_GetTightCurveBoundingBox_Helper( const ON_Curve& crv, ON_BoundingBox& bbox, const ON_Xform* xform, const ON_Xform* xform_inverse ) { // Get loose boundingbox of curve. ON_BoundingBox tempbox; if( !crv.GetBoundingBox(tempbox, false) ) return; // Transform the loose box if necessary. // Note: transforming a box might result in a larger box, // it's better to transform the curve, // which might actually result in a smaller box. if( xform_inverse ) { tempbox.Transform(*xform_inverse); } // If loose boundingbox of curve is inside partial result, return. if( bbox.Includes(tempbox, false) ) return; // Get tight boundingbox of curve, grow partial result. if( crv.GetTightBoundingBox(tempbox, false, xform) ) bbox.Union(tempbox); }
static void test_pci(ON_3dPoint &p, ON_Curve &c) { ON_wString wstr; ON_TextLog textlog(wstr); ON_ClassArray<ON_PX_EVENT> x; // Use default tolerance ON_Intersect(p, c, x); ON_3dPoint start = c.PointAtStart(); ON_3dPoint end = c.PointAtEnd(); bu_log("(%f,%f,%f) and [(%f,%f,%f) to (%f,%f,%f)]:\n", p[0], p[1], p[2], start[0], start[1], start[2], end[0], end[1], end[2]); if (x.Count() == 0) { bu_log("No intersection.\n"); } else { for (int i = 0; i < x.Count(); i++) x[i].Dump(textlog); ON_String str(wstr); bu_log(str.Array()); } bu_log("\n\n"); }
void ON_GL( const ON_Curve& curve, GLUnurbsObj* nobj, // created with gluNewNurbsRenderer ) GLenum type, // = 0 (and type is automatically set) double xform[][4] ) { const ON_PolyCurve* poly_curve = ON_PolyCurve::Cast(&curve); if ( poly_curve ) { ON_Curve* pSegmentCurve = 0; int segment_count = poly_curve->Count(); int i; for ( i = 0; i < segment_count; i++ ) { pSegmentCurve = poly_curve->SegmentCurve(i); if ( pSegmentCurve ) ON_GL( *pSegmentCurve, nobj, type, xform ); } return; } const ON_CurveProxy* curve_proxy = ON_CurveProxy::Cast(&curve); if ( curve_proxy && !curve_proxy->ProxyCurveIsReversed() ) { const ON_Curve* real_curve = curve_proxy->ProxyCurve(); if ( 0 == real_curve ) return; if ( curve_proxy == real_curve ) return; if ( curve_proxy->ProxyCurveDomain() == real_curve->Domain() ) { ON_GL( *real_curve, nobj, type, xform ); return; } } { ON_NurbsCurve tmp; const ON_NurbsCurve* nurbs_curve = ON_NurbsCurve::Cast(&curve); if ( !nurbs_curve ) { if ( curve.GetNurbForm(tmp) ) nurbs_curve = &tmp; } ON_GL( *nurbs_curve, nobj, type, true, NULL, xform ); } }
int ON_BrepExtrudeVertex( ON_Brep& brep, int vertex_index, const ON_Curve& path_curve ) { ON_3dVector path_vector; if ( vertex_index < 0 && vertex_index >= brep.m_V.Count() ) return false; if ( !ON_BrepExtrudeHelper_CheckPathCurve(path_curve,path_vector) ) return false; ON_Curve* c3 = path_curve.Duplicate(); brep.m_V.Reserve( brep.m_V.Count() + 1 ); ON_BrepVertex& v0 = brep.m_V[vertex_index]; ON_BrepVertex& v1 = brep.NewVertex( v0.point + path_vector, 0.0 ); c3->Translate( v0.point - c3->PointAtStart() ); int c3i = brep.AddEdgeCurve( c3 ); ON_BrepEdge& edge = brep.NewEdge( v0, v1, c3i ); edge.m_tolerance = 0.0; return true; }
ON_Surface::ISO ON_Surface::IsIsoparametric( const ON_Curve& curve, const ON_Interval* subdomain ) const { ISO iso = not_iso; if ( subdomain ) { ON_Interval cdom = curve.Domain(); double t0 = cdom.NormalizedParameterAt(subdomain->Min()); double t1 = cdom.NormalizedParameterAt(subdomain->Max()); if ( t0 < t1-ON_SQRT_EPSILON ) { if ( (t0 > ON_SQRT_EPSILON && t0 < 1.0-ON_SQRT_EPSILON) || (t1 > ON_SQRT_EPSILON && t1 < 1.0-ON_SQRT_EPSILON) ) { cdom.Intersection(*subdomain); if ( cdom.IsIncreasing() ) { ON_NurbsCurve nurbs_curve; if ( curve.GetNurbForm( nurbs_curve, 0.0,&cdom) ) { return IsIsoparametric( nurbs_curve, 0 ); } } } } } ON_BoundingBox bbox; double tolerance = 0.0; const int dim = curve.Dimension(); if ( (dim == 2 || dim==3) && curve.GetBoundingBox(bbox) ) { iso = IsIsoparametric( bbox ); switch (iso) { case x_iso: case W_iso: case E_iso: // make sure curve is a (nearly) vertical line // and weed out vertical scribbles tolerance = bbox.m_max.x - bbox.m_min.x; if ( tolerance < ON_ZERO_TOLERANCE && ON_ZERO_TOLERANCE*1024.0 <= (bbox.m_max.y-bbox.m_min.y) ) { // 26 March 2007 Dale Lear // If tolerance is tiny, then use ON_ZERO_TOLERANCE // This fixes cases where iso curves where not getting // the correct flag because tol=1e-16 and the closest // point to line had calculation errors of 1e-15. tolerance = ON_ZERO_TOLERANCE; } if ( !curve.IsLinear( tolerance ) ) iso = not_iso; break; case y_iso: case S_iso: case N_iso: // make sure curve is a (nearly) horizontal line // and weed out horizontal scribbles tolerance = bbox.m_max.y - bbox.m_min.y; if ( tolerance < ON_ZERO_TOLERANCE && ON_ZERO_TOLERANCE*1024.0 <= (bbox.m_max.x-bbox.m_min.x) ) { // 26 March 2007 Dale Lear // If tolerance is tiny, then use ON_ZERO_TOLERANCE // This fixes cases where iso curves where not getting // the correct flag because tol=1e-16 and the closest // point to line had calculation errors of 1e-15. tolerance = ON_ZERO_TOLERANCE; } if ( !curve.IsLinear( tolerance ) ) iso = not_iso; break; default: // nothing here break; } } return iso; }
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; }
// Criteria: // // 1. A linear edge associated with a planar face == 0 // 2. All linear edges associated with non-planar faces are part // of the same CSG shape AND all non-linear edges' non-planar faces // are also part of that same CSG shape = 1 // 3. If not 2, 0 int characterize_vert(struct subbrep_object_data *data, const ON_BrepVertex *v) { std::set<int> non_planar_faces; std::set<int>::iterator f_it; std::set<struct filter_obj *> fobjs; std::set<struct filter_obj *>::iterator fo_it; struct filter_obj *control = NULL; for (int i = 0; i < v->m_ei.Count(); i++) { std::set<int> efaces; const ON_BrepEdge *edge = &(data->brep->m_E[v->m_ei[i]]); ON_Curve *tc = edge->EdgeCurveOf()->Duplicate(); int is_linear = tc->IsLinear(); delete tc; // Get the faces associated with the edge for (int j = 0; j < edge->TrimCount(); j++) { ON_BrepTrim *trim = edge->Trim(j); efaces.insert(trim->Face()->m_face_index); } for(f_it = efaces.begin(); f_it != efaces.end(); f_it++) { struct filter_obj *new_obj; BU_GET(new_obj, struct filter_obj); surface_t stype = GetSurfaceType(data->brep->m_F[*f_it].SurfaceOf(), new_obj); if (stype == SURFACE_PLANE) { filter_obj_free(new_obj); BU_PUT(new_obj, struct filter_obj); if (is_linear) { for (fo_it = fobjs.begin(); fo_it != fobjs.end(); fo_it++) { struct filter_obj *obj = (struct filter_obj *)(*fo_it); filter_obj_free(obj); BU_PUT(obj, struct filter_obj); } return 0; } } else { if (!control) { control = new_obj; } else { fobjs.insert(new_obj); } } } } // Can this happen? if (fobjs.size() == 0) { if (control) { filter_obj_free(control); BU_PUT(control, struct filter_obj); } return 0; } int equal = 1; for(fo_it = fobjs.begin(); fo_it != fobjs.end(); fo_it++) { if (equal && !filter_objs_equal(*fo_it, control)) equal = 0; struct filter_obj *obj = (struct filter_obj *)(*fo_it); filter_obj_free(obj); BU_PUT(obj, struct filter_obj); } filter_obj_free(control); BU_PUT(control, struct filter_obj); return equal; }
void FindLoops(ON_Brep **b) { ON_3dPoint ptmatch, ptterminate, pstart, pend; int *curvearray; curvearray = static_cast<int*>(bu_malloc((*b)->m_C3.Count() * sizeof(int), "sketch edge list")); for (int i = 0; i < (*b)->m_C3.Count(); i++) { curvearray[i] = -1; } ON_SimpleArray<ON_Curve *> allsegments; ON_SimpleArray<ON_Curve *> loopsegments; int loop_complete; for (int i = 0; i < (*b)->m_C3.Count(); i++) { allsegments.Append((*b)->m_C3[i]); } int allcurvesassigned = 0; int assignedcount = 0; int curvecount = 0; int loopcount = 0; while (allcurvesassigned != 1) { int havefirstcurve = 0; while ((havefirstcurve == 0) && (curvecount < allsegments.Count())) { if (curvearray[curvecount] == -1) { havefirstcurve = 1; } else { curvecount++; } } // First, sort through things to assign curves to loops. loop_complete = 0; while ((loop_complete != 1) && (allcurvesassigned != 1)) { curvearray[curvecount] = loopcount; ptmatch = (*b)->m_C3[curvecount]->PointAtEnd(); ptterminate = (*b)->m_C3[curvecount]->PointAtStart(); for (int i = 0; i < allsegments.Count(); i++) { pstart = (*b)->m_C3[i]->PointAtStart(); pend = (*b)->m_C3[i]->PointAtEnd(); if (NEAR_ZERO(ptmatch.DistanceTo(pstart), ON_ZERO_TOLERANCE) && (curvearray[i] == -1)) { curvecount = i; ptmatch = pend; i = allsegments.Count(); if (NEAR_ZERO(pend.DistanceTo(ptterminate), ON_ZERO_TOLERANCE)) { loop_complete = 1; loopcount++; } } else { if (i == allsegments.Count() - 1) { loop_complete = 1; //If we reach this pass, loop had better be complete loopcount++; assignedcount = 0; for (int j = 0; j < allsegments.Count(); j++) { if (curvearray[j] != -1) assignedcount++; } if (allsegments.Count() == assignedcount) allcurvesassigned = 1; } } } } } double maxdist = 0.0; int largest_loop_index = 0; for (int i = 0; i <= loopcount ; i++) { ON_BoundingBox lbbox; for (int j = 0; j < (*b)->m_C3.Count(); j++) { if (curvearray[j] == i) { ON_Curve *currcurve = (*b)->m_C3[j]; currcurve->GetBoundingBox(lbbox, true); } } point_t minpt, maxpt; double currdist; VSET(minpt, lbbox.m_min[0], lbbox.m_min[1], lbbox.m_min[2]); VSET(maxpt, lbbox.m_max[0], lbbox.m_max[1], lbbox.m_max[2]); currdist = DIST_PT_PT(minpt, maxpt); if (currdist > maxdist) { maxdist = currdist; largest_loop_index = i; } } for (int i = 0; i < allsegments.Count(); i++) { if (curvearray[i] == largest_loop_index) loopsegments.Append((*b)->m_C3[i]); } (*b)->NewPlanarFaceLoop(0, ON_BrepLoop::outer, loopsegments, true); loopsegments.Empty(); // If there's anything left, make inner loops out of it for (int i = 0; i <= loopcount; i++) { if (i != largest_loop_index) { for (int j = 0; j < allsegments.Count(); j++) { if (curvearray[j] == i) loopsegments.Append((*b)->m_C3[j]); } (*b)->NewPlanarFaceLoop(0, ON_BrepLoop::inner, loopsegments, true); } loopsegments.Empty(); } bu_free(curvearray, "sketch edge list"); }
void subbrep_planar_init(struct subbrep_object_data *data) { if (!data) return; if (data->planar_obj) return; BU_GET(data->planar_obj, struct subbrep_object_data); subbrep_object_init(data->planar_obj, data->brep); bu_vls_sprintf(data->planar_obj->key, "%s", bu_vls_addr(data->key)); data->planar_obj->obj_cnt = data->obj_cnt; (*data->obj_cnt)++; bu_vls_sprintf(data->planar_obj->name_root, "%s_%d", bu_vls_addr(data->name_root), *(data->obj_cnt)); data->planar_obj->type = PLANAR_VOLUME; data->planar_obj->local_brep = ON_Brep::New(); std::map<int, int> face_map; std::map<int, int> surface_map; std::map<int, int> edge_map; std::map<int, int> vertex_map; std::map<int, int> loop_map; std::map<int, int> c3_map; std::map<int, int> c2_map; std::map<int, int> trim_map; std::set<int> faces; std::set<int> fil; std::set<int> loops; std::set<int> skip_verts; std::set<int> skip_edges; std::set<int> keep_verts; std::set<int> partial_edges; std::set<int> isolated_trims; // collect 2D trims whose parent loops aren't fully included here array_to_set(&faces, data->faces, data->faces_cnt); array_to_set(&fil, data->fil, data->fil_cnt); array_to_set(&loops, data->loops, data->loops_cnt); std::map<int, std::set<int> > face_loops; std::map<int, std::set<int> >::iterator fl_it; std::set<int>::iterator l_it; for (int i = 0; i < data->edges_cnt; i++) { int c3i; int new_edge_curve = 0; const ON_BrepEdge *old_edge = &(data->brep->m_E[data->edges[i]]); //std::cout << "old edge: " << old_edge->Vertex(0)->m_vertex_index << "," << old_edge->Vertex(1)->m_vertex_index << "\n"; // See if the vertices from this edge play a role in the planar volume int use_edge = 2; for (int vi = 0; vi < 2; vi++) { int vert_test = -1; int vert_ind = old_edge->Vertex(vi)->m_vertex_index; if (skip_verts.find(vert_ind) != skip_verts.end()) { vert_test = 1; } if (vert_test == -1 && keep_verts.find(vert_ind) != keep_verts.end()) { vert_test = 0; } if (vert_test == -1) { vert_test = characterize_vert(data, old_edge->Vertex(vi)); if (vert_test) { skip_verts.insert(vert_ind); ON_3dPoint vp = old_edge->Vertex(vi)->Point(); bu_log("vert %d (%f %f %f): %d\n", vert_ind, vp.x, vp.y, vp.z, vert_test); } else { keep_verts.insert(vert_ind); } } if (vert_test == 1) { use_edge--; } } if (use_edge == 0) { bu_log("skipping edge %d - both verts are skips\n", old_edge->m_edge_index); skip_edges.insert(old_edge->m_edge_index); continue; } if (use_edge == 1) { bu_log("One of the verts for edge %d is a skip.\n", old_edge->m_edge_index); partial_edges.insert(old_edge->m_edge_index); continue; } // Get the 3D curves from the edges if (c3_map.find(old_edge->EdgeCurveIndexOf()) == c3_map.end()) { ON_Curve *nc = old_edge->EdgeCurveOf()->Duplicate(); ON_Curve *tc = old_edge->EdgeCurveOf()->Duplicate(); if (tc->IsLinear()) { c3i = data->planar_obj->local_brep->AddEdgeCurve(nc); c3_map[old_edge->EdgeCurveIndexOf()] = c3i; } else { ON_Curve *c3 = new ON_LineCurve(old_edge->Vertex(0)->Point(), old_edge->Vertex(1)->Point()); c3i = data->planar_obj->local_brep->AddEdgeCurve(c3); c3_map[old_edge->EdgeCurveIndexOf()] = c3i; new_edge_curve = 1; } } else { c3i = c3_map[old_edge->EdgeCurveIndexOf()]; } // Get the vertices from the edges int v[2]; for (int vi = 0; vi < 2; vi++) { if (vertex_map.find(old_edge->Vertex(vi)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(old_edge->Vertex(vi)->Point(), old_edge->Vertex(vi)->m_tolerance); v[vi] = newvvi.m_vertex_index; vertex_map[old_edge->Vertex(vi)->m_vertex_index] = v[vi]; } else { v[vi] = vertex_map[old_edge->Vertex(vi)->m_vertex_index]; } } ON_BrepEdge& new_edge = data->planar_obj->local_brep->NewEdge(data->planar_obj->local_brep->m_V[v[0]], data->planar_obj->local_brep->m_V[v[1]], c3i, NULL ,0); edge_map[old_edge->m_edge_index] = new_edge.m_edge_index; // Get the 2D curves from the trims for (int j = 0; j < old_edge->TrimCount(); j++) { ON_BrepTrim *old_trim = old_edge->Trim(j); if (faces.find(old_trim->Face()->m_face_index) != faces.end()) { if (c2_map.find(old_trim->TrimCurveIndexOf()) == c2_map.end()) { ON_Curve *nc = old_trim->TrimCurveOf()->Duplicate(); int c2i = data->planar_obj->local_brep->AddTrimCurve(nc); c2_map[old_trim->TrimCurveIndexOf()] = c2i; //std::cout << "c2i: " << c2i << "\n"; } } } // Get the faces and surfaces from the trims for (int j = 0; j < old_edge->TrimCount(); j++) { ON_BrepTrim *old_trim = old_edge->Trim(j); if (face_map.find(old_trim->Face()->m_face_index) == face_map.end()) { if (faces.find(old_trim->Face()->m_face_index) != faces.end()) { ON_Surface *ns = old_trim->Face()->SurfaceOf()->Duplicate(); ON_Surface *ts = old_trim->Face()->SurfaceOf()->Duplicate(); if (ts->IsPlanar(NULL, BREP_PLANAR_TOL)) { int nsid = data->planar_obj->local_brep->AddSurface(ns); surface_map[old_trim->Face()->SurfaceIndexOf()] = nsid; ON_BrepFace &new_face = data->planar_obj->local_brep->NewFace(nsid); face_map[old_trim->Face()->m_face_index] = new_face.m_face_index; //std::cout << "old face " << old_trim->Face()->m_face_index << " is now " << new_face.m_face_index << "\n"; if (fil.find(old_trim->Face()->m_face_index) != fil.end()) { data->planar_obj->local_brep->FlipFace(new_face); } } } } } // Get the loops from the trims for (int j = 0; j < old_edge->TrimCount(); j++) { ON_BrepTrim *old_trim = old_edge->Trim(j); ON_BrepLoop *old_loop = old_trim->Loop(); if (face_map.find(old_trim->Face()->m_face_index) != face_map.end()) { if (loops.find(old_loop->m_loop_index) != loops.end()) { if (loop_map.find(old_loop->m_loop_index) == loop_map.end()) { face_loops[old_trim->Face()->m_face_index].insert(old_loop->m_loop_index); } } } } } for (fl_it = face_loops.begin(); fl_it != face_loops.end(); fl_it++) { int loop_cnt = fl_it->second.size(); if (loop_cnt == 1) { // If we have only one loop on a face it's an outer loop, // whatever it was in the original brep. const ON_BrepLoop *old_loop = &(data->brep->m_L[*(fl_it->second.begin())]); ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::outer, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]); loop_map[old_loop->m_loop_index] = nl.m_loop_index; } else { bu_log("loop_cnt: %d\n", loop_cnt); // If we ended up with multiple loops, one of them should be an outer loop // and the rest inner loops // Get the outer loop first for (l_it = fl_it->second.begin(); l_it != fl_it->second.end(); l_it++) { const ON_BrepLoop *old_loop = &(data->brep->m_L[*l_it]); if (data->brep->LoopDirection(data->brep->m_L[*l_it]) == 1) { ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::outer, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]); loop_map[old_loop->m_loop_index] = nl.m_loop_index; } } // Now get the inner loops; for (l_it = fl_it->second.begin(); l_it != fl_it->second.end(); l_it++) { const ON_BrepLoop *old_loop = &(data->brep->m_L[*l_it]); if (data->brep->LoopDirection(data->brep->m_L[*l_it]) != 1) { ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::inner, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]); loop_map[old_loop->m_loop_index] = nl.m_loop_index; } } } } // Now, create new trims using the old loop definitions and the maps std::map<int, int>::iterator loop_it; std::set<int> evaluated; for (loop_it = loop_map.begin(); loop_it != loop_map.end(); loop_it++) { const ON_BrepLoop *old_loop = &(data->brep->m_L[(*loop_it).first]); ON_BrepLoop &new_loop = data->planar_obj->local_brep->m_L[(*loop_it).second]; for (int j = 0; j < old_loop->TrimCount(); j++) { const ON_BrepTrim *old_trim = old_loop->Trim(j); ON_BrepEdge *o_edge = old_trim->Edge(); if (!o_edge) { /* If we didn't have an edge originally, we need to add the 2d curve here */ if (c2_map.find(old_trim->TrimCurveIndexOf()) == c2_map.end()) { ON_Curve *nc = old_trim->TrimCurveOf()->Duplicate(); int c2i = data->planar_obj->local_brep->AddTrimCurve(nc); c2_map[old_trim->TrimCurveIndexOf()] = c2i; } if (vertex_map.find(old_trim->Vertex(0)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvs = data->planar_obj->local_brep->NewVertex(old_trim->Vertex(0)->Point(), old_trim->Vertex(0)->m_tolerance); vertex_map[old_trim->Vertex(0)->m_vertex_index] = newvs.m_vertex_index; ON_BrepTrim &nt = data->planar_obj->local_brep->NewSingularTrim(newvs, new_loop, old_trim->m_iso, c2_map[old_trim->TrimCurveIndexOf()]); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; } else { ON_BrepTrim &nt = data->planar_obj->local_brep->NewSingularTrim(data->planar_obj->local_brep->m_V[vertex_map[old_trim->Vertex(0)->m_vertex_index]], new_loop, old_trim->m_iso, c2_map[old_trim->TrimCurveIndexOf()]); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; } continue; } if (evaluated.find(o_edge->m_edge_index) != evaluated.end()) { bu_log("edge %d already handled, continuing...\n", o_edge->m_edge_index); continue; } // Don't use a trim connected to an edge we are skipping if (skip_edges.find(o_edge->m_edge_index) != skip_edges.end()) { bu_log("edge %d is skipped, continuing...\n", o_edge->m_edge_index); evaluated.insert(o_edge->m_edge_index); continue; } int is_partial = 0; if (partial_edges.find(o_edge->m_edge_index) != partial_edges.end()) is_partial = 1; if (!is_partial) { ON_BrepEdge &n_edge = data->planar_obj->local_brep->m_E[edge_map[o_edge->m_edge_index]]; ON_Curve *ec = o_edge->EdgeCurveOf()->Duplicate(); if (ec->IsLinear()) { ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(n_edge, old_trim->m_bRev3d, new_loop, c2_map[old_trim->TrimCurveIndexOf()]); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; nt.m_iso = old_trim->m_iso; } else { // Wasn't linear, but wasn't partial either - replace with a line ON_Curve *c2_orig = old_trim->TrimCurveOf()->Duplicate(); ON_3dPoint p1 = c2_orig->PointAt(c2_orig->Domain().Min()); ON_3dPoint p2 = c2_orig->PointAt(c2_orig->Domain().Max()); ON_Curve *c2 = new ON_LineCurve(p1, p2); c2->ChangeDimension(2); int c2i = data->planar_obj->local_brep->AddTrimCurve(c2); ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(n_edge, old_trim->m_bRev3d, new_loop, c2i); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; nt.m_iso = old_trim->m_iso; delete c2_orig; } delete ec; } else { // Partial edge - let the fun begin ON_3dPoint p1, p2; ON_BrepEdge *next_edge; bu_log("working a partial edge: %d\n", o_edge->m_edge_index); int v[2]; v[0] = o_edge->Vertex(0)->m_vertex_index; v[1] = o_edge->Vertex(1)->m_vertex_index; // figure out which trim point we can use, the min or max int pos1 = 0; if (skip_verts.find(v[0]) != skip_verts.end()) { pos1 = 1; } int j_next = j; ON_Curve *c2_orig = old_trim->TrimCurveOf()->Duplicate(); ON_Curve *c2_next = NULL; int walk_dir = 1; // bump the loop iterator to get passed any skipped edges to // the next partial while (!c2_next) { (walk_dir == 1) ? j_next++ : j_next--; if (j_next == old_loop->TrimCount()) { j_next = 0; } if (j_next == -1) { j_next = old_loop->TrimCount() - 1; } const ON_BrepTrim *next_trim = old_loop->Trim(j_next); next_edge = next_trim->Edge(); if (!next_edge) continue; if (skip_edges.find(next_edge->m_edge_index) == skip_edges.end()) { if (partial_edges.find(next_edge->m_edge_index) != partial_edges.end()) { bu_log("found next partial edge %d\n", next_edge->m_edge_index); evaluated.insert(next_edge->m_edge_index); c2_next = next_trim->TrimCurveOf()->Duplicate(); } else { bu_log("partial edge %d followed by non-partial %d, need to go the other way\n", o_edge->m_edge_index, next_edge->m_edge_index); j_next--; walk_dir = -1; } } else { bu_log("skipping fully ignored edge %d\n", next_edge->m_edge_index); evaluated.insert(next_edge->m_edge_index); } } int v2[2]; v2[0] = next_edge->Vertex(0)->m_vertex_index; v2[1] = next_edge->Vertex(1)->m_vertex_index; // figure out which trim point we can use, the min or max int pos2 = 0; if (skip_verts.find(v2[0]) != skip_verts.end()) { pos2 = 1; } int vmapped[2]; if (vertex_map.find(o_edge->Vertex(pos1)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(o_edge->Vertex(pos1)->Point(), o_edge->Vertex(pos1)->m_tolerance); vertex_map[o_edge->Vertex(pos1)->m_vertex_index] = newvvi.m_vertex_index; } if (vertex_map.find(next_edge->Vertex(pos2)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(next_edge->Vertex(pos2)->Point(), next_edge->Vertex(pos2)->m_tolerance); vertex_map[next_edge->Vertex(pos2)->m_vertex_index] = newvvi.m_vertex_index; } // If walk_dir is -1, need to flip things around (I think...) the verts and trim points // will be swapped compared to a forward walk if (walk_dir == -1) { vmapped[1] = vertex_map[o_edge->Vertex(pos1)->m_vertex_index]; vmapped[0] = vertex_map[next_edge->Vertex(pos2)->m_vertex_index]; } else { vmapped[0] = vertex_map[o_edge->Vertex(pos1)->m_vertex_index]; vmapped[1] = vertex_map[next_edge->Vertex(pos2)->m_vertex_index]; } // New Edge curve ON_Curve *c3 = new ON_LineCurve(o_edge->Vertex(pos1)->Point(), next_edge->Vertex(pos2)->Point()); int c3i = data->planar_obj->local_brep->AddEdgeCurve(c3); ON_BrepEdge& new_edge = data->planar_obj->local_brep->NewEdge(data->planar_obj->local_brep->m_V[vmapped[0]], data->planar_obj->local_brep->m_V[vmapped[1]], c3i, NULL ,0); // Again, flip if walk_dir is -1 if (walk_dir == -1) { p2 = c2_orig->PointAt(c2_orig->Domain().Min()); p1 = c2_next->PointAt(c2_orig->Domain().Max()); } else { p1 = c2_orig->PointAt(c2_orig->Domain().Min()); p2 = c2_next->PointAt(c2_orig->Domain().Max()); } std::cout << "p1: " << pout(p1) << "\n"; std::cout << "p2: " << pout(p2) << "\n"; ON_Curve *c2 = new ON_LineCurve(p1, p2); c2->ChangeDimension(2); int c2i = data->planar_obj->local_brep->AddTrimCurve(c2); ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(new_edge, false, new_loop, c2i); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; nt.m_iso = old_trim->m_iso; delete c2_orig; delete c2_next; } } } // If there is a possibility of a negative volume for the planar solid, do a test. // The only way to get a negative planar solid in this context is if that solid is // "inside" a non-planar shape (it would be "part of" the parent shape if it were // planar and it would be a separate shape altogether if it were not topologically // connected. So we take one partial edge, find its associated non-planar faces, // and collect all the partial and skipped edges from that face and any non-planar // faces associated with the other partial/skipped edges. // // TODO - We still have an unhandled possibility here - the self-intersecting // planar_obj. For example: // // * * // * * * * // * * * * * * // * * * * * * * * // * * * * * * // * * * * * * * * * * * * // if (partial_edges.size() > 0) { std::queue<int> connected_faces; std::set<int> relevant_edges; std::set<int>::iterator re_it; std::set<int> efaces; std::set<int>::iterator f_it; std::set<int> found_faces; const ON_BrepEdge *seed_edge = &(data->brep->m_E[*partial_edges.begin()]); for (int j = 0; j < seed_edge->TrimCount(); j++) { ON_BrepTrim *trim = seed_edge->Trim(j); efaces.insert(trim->Face()->m_face_index); } for(f_it = efaces.begin(); f_it != efaces.end(); f_it++) { surface_t stype = GetSurfaceType(data->brep->m_F[*f_it].SurfaceOf(), NULL); if (stype != SURFACE_PLANE) { connected_faces.push(data->brep->m_F[*f_it].m_face_index); } } while (!connected_faces.empty()) { int face_index = connected_faces.front(); connected_faces.pop(); std::set<int> local_edges; std::set<int>::iterator le_it; found_faces.insert(face_index); const ON_BrepFace *face = &(data->brep->m_F[face_index]); const ON_BrepLoop *loop = NULL; // Find the loop in this face that is associated with this subbrep for (int i = 0; i < face->LoopCount(); i++) { int loop_ind = face->Loop(i)->m_loop_index; if (loops.find(loop_ind) != loops.end()) { loop = &(data->brep->m_L[loop_ind]); break; } } // Collect the edges that are partial or skipped for (int i = 0; i < loop->TrimCount(); i++) { const ON_BrepTrim *trim = loop->Trim(i); ON_BrepEdge *edge = trim->Edge(); if (edge) { if (partial_edges.find(edge->m_edge_index) != partial_edges.end()) { relevant_edges.insert(edge->m_edge_index); local_edges.insert(edge->m_edge_index); } if (skip_edges.find(edge->m_edge_index) != skip_edges.end()) { relevant_edges.insert(edge->m_edge_index); local_edges.insert(edge->m_edge_index); } } } // For each collected partial/skipped edge, add any faces not already // found to the queue. for (le_it = local_edges.begin(); le_it != local_edges.end(); le_it++) { const ON_BrepEdge *edge = &(data->brep->m_E[*le_it]); for (int j = 0; j < edge->TrimCount(); j++) { ON_BrepTrim *trim = edge->Trim(j); if (found_faces.find(trim->Face()->m_face_index) == found_faces.end()) { found_faces.insert(trim->Face()->m_face_index); connected_faces.push(trim->Face()->m_face_index); } } } } // Build two bounding boxes - one with the new verts in planar_obj, and the other with // the edges found above. ON_BoundingBox pbb, ebb; ON_MinMaxInit(&pbb.m_min, &pbb.m_max); ON_MinMaxInit(&ebb.m_min, &ebb.m_max); for (int i = 0; i < data->planar_obj->local_brep->m_V.Count(); i++) { const ON_BrepVertex *v = &(data->planar_obj->local_brep->m_V[i]); pbb.Set(v->Point(), true); } for (re_it = relevant_edges.begin(); re_it != relevant_edges.end(); re_it++) { const ON_BrepEdge *e = &(data->brep->m_E[*re_it]); ON_BoundingBox cbb = e->EdgeCurveOf()->BoundingBox(); ebb.Set(cbb.m_min, true); ebb.Set(cbb.m_max, true); } //std::cout << "in pbb.s rpp " << pout(pbb.m_min) << " " << pout(pbb.m_max) << "\n"; //std::cout << "in ebb.s rpp " << pout(ebb.m_min) << " " << pout(ebb.m_max) << "\n"; if (ebb.Includes(pbb)) { bu_log("negative volume\n"); data->planar_obj->negative_shape = -1; } else { bu_log("positive volume\n"); data->planar_obj->negative_shape = 1; } data->planar_obj->params->bool_op = (data->planar_obj->negative_shape == -1) ? '-' : 'u'; } // Need to preserve the vertex map for this, since we're not done building up the brep map_to_array(&(data->planar_obj->planar_obj_vert_map), &(data->planar_obj->planar_obj_vert_cnt), &vertex_map); data->planar_obj->local_brep->SetTrimTypeFlags(true); }
void FindLoops(ON_Brep **b, const ON_Line* revaxis, const fastf_t ang) { ON_3dPoint ptmatch, ptterminate, pstart, pend; int *curvearray; curvearray = static_cast<int*>(bu_malloc((*b)->m_C3.Count() * sizeof(int), "sketch edge list")); for (int i = 0; i < (*b)->m_C3.Count(); i++) { curvearray[i] = -1; } ON_SimpleArray<ON_Curve *> allsegments; ON_SimpleArray<ON_Curve *> loopsegments; int loop_complete; for (int i = 0; i < (*b)->m_C3.Count(); i++) { allsegments.Append((*b)->m_C3[i]); } int allcurvesassigned = 0; int assignedcount = 0; int curvecount = 0; int loopcount = 0; while (allcurvesassigned != 1) { int havefirstcurve = 0; while ((havefirstcurve == 0) && (curvecount < allsegments.Count())) { if (curvearray[curvecount] == -1) { havefirstcurve = 1; } else { curvecount++; } } // First, sort through things to assign curves to loops. loop_complete = 0; while ((loop_complete != 1) && (allcurvesassigned != 1)) { curvearray[curvecount] = loopcount; ptmatch = (*b)->m_C3[curvecount]->PointAtEnd(); ptterminate = (*b)->m_C3[curvecount]->PointAtStart(); for (int i = 0; i < allsegments.Count(); i++) { pstart = (*b)->m_C3[i]->PointAtStart(); pend = (*b)->m_C3[i]->PointAtEnd(); if (NEAR_ZERO(ptmatch.DistanceTo(pstart), ON_ZERO_TOLERANCE) && (curvearray[i] == -1)) { curvecount = i; ptmatch = pend; i = allsegments.Count(); if (NEAR_ZERO(pend.DistanceTo(ptterminate), ON_ZERO_TOLERANCE)) { loop_complete = 1; loopcount++; } } else { if (i == allsegments.Count() - 1) { loop_complete = 1; //If we reach this pass, loop had better be complete loopcount++; assignedcount = 0; for (int j = 0; j < allsegments.Count(); j++) { if (curvearray[j] != -1) assignedcount++; } if (allsegments.Count() == assignedcount) allcurvesassigned = 1; } } } } } double maxdist = 0.0; int largest_loop_index = 0; for (int i = 0; i <= loopcount ; i++) { ON_BoundingBox lbbox; for (int j = 0; j < (*b)->m_C3.Count(); j++) { if (curvearray[j] == i) { ON_Curve *currcurve = (*b)->m_C3[j]; currcurve->GetBoundingBox(lbbox, true); } } point_t minpt, maxpt; double currdist; VSET(minpt, lbbox.m_min[0], lbbox.m_min[1], lbbox.m_min[2]); VSET(maxpt, lbbox.m_max[0], lbbox.m_max[1], lbbox.m_max[2]); currdist = DIST_PT_PT(minpt, maxpt); if (currdist > maxdist) { maxdist = currdist; largest_loop_index = i; } } for (int i = 0; i < loopcount ; i++) { ON_PolyCurve* poly_curve = new ON_PolyCurve(); for (int j = 0; j < allsegments.Count(); j++) { if (curvearray[j] == i) { poly_curve->Append(allsegments[j]); } } ON_NurbsCurve *revcurve = ON_NurbsCurve::New(); poly_curve->GetNurbForm(*revcurve); ON_RevSurface* revsurf = ON_RevSurface::New(); revsurf->m_curve = revcurve; revsurf->m_axis = *revaxis; revsurf->m_angle = ON_Interval(0, ang); ON_BrepFace *face = (*b)->NewFace(*revsurf); if (i == largest_loop_index) { (*b)->FlipFace(*face); } } bu_free(curvearray, "sketch edge list"); }
int main(int, char**) { srand(time(0)); ON_3dPoint center(0.0, 0.0, 0.0); double radius = 10.0; ON_Sphere sphere(center, radius); ON_Brep *brep = ON_BrepSphere(sphere); ON_3dPoint p1(0.0, 0.0, 0.0); ON_3dPoint p2(0.0, 0.0, radius); // Point-point intersection bu_log("*** Point-point intersection ***\n"); test_ppi(p1, p1); test_ppi(p1, p2); // Point-curve intersection bu_log("*** Point-curve intersection ***\n"); // brep->m_C3[0] is an arc curve that starts from (0, 0, -R) // to (0, 0, R) through (R, 0, 0) which forms a semicircle. ON_Curve *curve = brep->m_C3[0]; ON_3dPoint mid = curve->PointAt(curve->Domain().Mid()); bu_log("debug: %f %f %f\n", mid[0], mid[1], mid[2]); bu_log("** Part 1 **\n"); test_pci(p1, *curve); test_pci(p2, *curve); // Now we use some randomized points (should intersect) bu_log("** Part 2 **\n"); for (int i = 0; i < 10; i++) { double x = rand_f(0.0, radius); double y = 0.0; double z = sqrt(radius*radius-x*x); if (rand() % 2) z = -z; // sometimes we have it negative ON_3dPoint test_pt(x, y, z); test_pci(test_pt, *curve); } // More randomize points (maybe no intersection) bu_log("** Part 3 **\n"); for (int i = 0; i < 10; i++) { // We use test points randomly distributed inside a cube // from (-R, -R, -R) to (R, R, R) double x = rand_f(-radius, radius); double y = rand_f(-radius, radius); double z = rand_f(-radius, radius); ON_3dPoint test_pt(x, y, z); test_pci(test_pt, *curve); } // Point-surface intersection bu_log("*** Point-surface intersection ***\n"); bu_log("** Part 1 **\n"); ON_Surface *surf = brep->m_S[0]; test_psi(p1, *surf); test_psi(p2, *surf); // Now we use some randomized points (should intersect) bu_log("** Part 2 **\n"); for (int i = 0; i < 10; i++) { double x = rand_f(-radius, radius); double y_range = sqrt(radius*radius-x*x); double y = rand_f(-y_range, y_range); double z = sqrt(y_range*y_range-y*y); if (rand() % 2) z = -z; // sometimes we have it negative ON_3dPoint test_pt(x, y, z); test_psi(test_pt, *surf); } // More randomize points (maybe no intersection) bu_log("** Part 3 **\n"); for (int i = 0; i < 10; i++) { // We use test points randomly distributed inside a cube // from (-R, -R, -R) to (R, R, R) double x = rand_f(-radius, radius); double y = rand_f(-radius, radius); double z = rand_f(-radius, radius); ON_3dPoint test_pt(x, y, z); test_psi(test_pt, *surf); } delete brep; bu_log("All finished.\n"); return 0; }
// Add the isocurves of a BrepFace to the partial boundingbox result. static void ON_Brep_GetTightIsoCurveBoundingBox_Helper( const TL_Brep& tlbrep, const ON_BrepFace& face, ON_BoundingBox& bbox, const ON_Xform* xform, int dir ) { ON_Interval domain = face.Domain(1 - dir); int degree = face.Degree(1 - dir); int spancount = face.SpanCount(1 - dir); int spansamples = degree * (degree + 1) - 1; if( spansamples < 2 ) spansamples = 2; // pbox delineates the extremes of the face interior. // We can use it to trivially reject spans and isocurves. ON_BrepLoop* pOuterLoop = face.OuterLoop(); if( NULL==pOuterLoop ) return; const ON_BoundingBox& pbox = pOuterLoop->m_pbox; double t0 = ((dir == 0) ? pbox.Min().y : pbox.Min().x); double t1 = ((dir == 0) ? pbox.Max().y : pbox.Max().x); // Get the surface span vector. ON_SimpleArray<double> spanvector(spancount + 1); spanvector.SetCount(spancount + 1); face.GetSpanVector(1 - dir, spanvector.Array()); // Generate a list of all the sampling parameters. ON_SimpleArray<double> samples(spancount * spansamples); for( int s = 0; s < spancount; s++) { double s0 = spanvector[s]; double s1 = spanvector[s+1]; // Reject span if it does not intersect the pbox. if( s1 < t0 ) { continue; } if( s0 > t1 ) { continue; } ON_Interval span(s0, s1); for( int i = 1; i < spansamples; i++ ) { double t = span.ParameterAt((double)i / (double)(spansamples - 1)); // Reject iso if it does not intersect the pbox. if( t < t0 ) continue; if( t > t1 ) break; samples.Append(t); } } //Iterate over samples int sample_count = samples.Count(); ON_BoundingBox loose_box; ON_SimpleArray<ON_Interval> intervals; ON_NurbsCurve isosubcrv; for( int i = 0; i<sample_count; i++) { // Retrieve iso-curve. ON_Curve* isocrv = face.IsoCurve(dir, samples[i]); while( NULL!=isocrv ) { // Transform isocurve if necessary, this is better than transforming downstream boundingboxes. if( xform ) isocrv->Transform(*xform); // Compute loose box. if( !isocrv->GetBoundingBox(loose_box, false)) break; // Determine whether the loose box is already contained within the partial result. if( bbox.Includes(loose_box, false) ) break; // Solve trimming domains for the iso-curve. intervals.SetCount(0); if( !tlbrep.GetIsoIntervals(face, dir, samples[i], intervals)) break; // Iterate over trimmed iso-curves. int interval_count = intervals.Count(); for( int k=0; k<interval_count; k++ ) { //this to mask a bug in Rhino4. GetNurbForm does not destroy the Curve Tree. It does now. isosubcrv.DestroyCurveTree(); isocrv->GetNurbForm(isosubcrv, 0.0, &intervals[k]); ON_Brep_GetTightCurveBoundingBox_Helper(isosubcrv, bbox, NULL, NULL); } break; } if( isocrv ) { delete isocrv; isocrv = NULL; } } }
bool ON_Brep::SplitKinkyEdge( int edge_index, double kink_tol_radians ) { // Default kink_tol_radians MUST BE ON_PI/180.0. // // The default kink tol must be kept in sync with the default for // TL_Brep::SplitKinkyFace() and ON_Brep::SplitKinkyFace(). // See comments in TL_Brep::SplitKinkyFace() for more details. bool rc = true; if (kink_tol_radians < ON_ZERO_TOLERANCE) kink_tol_radians = ON_ZERO_TOLERANCE; else if (kink_tol_radians > ON_PI - ON_ZERO_TOLERANCE) kink_tol_radians = ON_PI - ON_ZERO_TOLERANCE; double atol = cos(kink_tol_radians); if (edge_index < 0 || edge_index >= m_E.Count()) return false; ON_BrepEdge& E = m_E[edge_index]; if (E.m_c3i < 0) return false; ON_SimpleArray<double> split_t(4); double t0 = E.Domain()[0]; int hint = 0; ON_Curve* curve = m_C3[E.m_c3i]; if (!curve) return false; int scount = curve->SpanCount(); while (split_t.Count() < scount){ double t; if (!E.GetNextDiscontinuity(ON::G1_continuous, t0, E.Domain()[1], &t, &hint, NULL, atol)) break; split_t.Append(t); t0 = t; } if (split_t.Count() >= scount) return false; if (split_t.Count() == 0) return true;//no kinks split_t.Reverse(); for (int i=0; i<split_t.Count(); i++){ //if split parameter is near start or end, just adjust domain. double t0, t1; m_E[edge_index].GetDomain(&t0, &t1); if (t1 - t0 < 10.0*ON_ZERO_TOLERANCE) continue; //6 Dec 2002 Dale Lear: // I added the relative edge_split_s and trm_split_s tests to detect // attempts to trim a nano-gnats-wisker of the end of a trim. // set to true if edge should be trimmed instead of split. bool bTrimEdgeEnd = false; double edge_split_s = ON_Interval(t0,t1).NormalizedParameterAt(split_t[i]); double trim_split_s = 0.5; if (split_t[i] - t0 <= ON_ZERO_TOLERANCE || edge_split_s <= ON_SQRT_EPSILON ) { continue; } if (t1 - split_t[i] <= ON_ZERO_TOLERANCE || edge_split_s >= 1.0-ON_SQRT_EPSILON) { continue; } // trim_t[] = corresponding trim parameters ON_SimpleArray<double> trim_t(m_E[edge_index].m_ti.Count()); if ( !bTrimEdgeEnd ) { for (int j=0; j<m_E[edge_index].m_ti.Count(); j++) { double t; if (!GetTrimParameter(m_E[edge_index].m_ti[j], split_t[i], &t)){ rc = false; continue; } trim_t.Append(t); const ON_BrepTrim& trim = m_T[m_E[edge_index].m_ti[j]]; ON_Interval trim_domain = trim.Domain(); trim_split_s = trim_domain.NormalizedParameterAt(t); if ( trim_split_s <= ON_SQRT_EPSILON || t - trim_domain[0] <= ON_ZERO_TOLERANCE ) { bTrimEdgeEnd = true; break; } if ( trim_split_s >= 1.0-ON_SQRT_EPSILON || trim_domain[1] - t <= ON_ZERO_TOLERANCE ) { bTrimEdgeEnd = true; break; } } } if ( bTrimEdgeEnd ) { // if we get here, a split parameter we got was too close to // the end of the edge or a trim for us to split it. if ( edge_split_s <= 0.01 ) { if ( t0 < split_t[i] ) m_E[edge_index].ON_CurveProxy::Trim(ON_Interval(split_t[i], t1)); } else if ( edge_split_s >= 0.99 ) { if ( split_t[i] < t1 ) m_E[edge_index].ON_CurveProxy::Trim(ON_Interval(t0, split_t[i])); } else { // no decent agreement between trims and edges - continue // with other parameters but this is basically the same // thing as having SplitEdge() fail. rc = false; } continue; } if (!SplitEdge(edge_index, split_t[i], trim_t)){ rc = false; continue; } ON_Curve* new_curve0 = m_E[edge_index].DuplicateCurve(); if (new_curve0){ m_E[edge_index].m_c3i = AddEdgeCurve(new_curve0); m_E[edge_index].SetProxyCurve(new_curve0); } ON_Curve* new_curve1 = m_E.Last()->DuplicateCurve(); if (new_curve1){ m_E.Last()->m_c3i = AddEdgeCurve(new_curve1); m_E.Last()->SetProxyCurve(new_curve1); } } return rc; }