#include "Stdafx.h" #include "CutSolidAlgo.h" #include "CutSurfaceAlgo.h" #include "BRepClass3d_SolidClassifier.hxx" CutSolidAlgo::CutSolidAlgo(void) { } CutSolidAlgo::CutSolidAlgo( TopoDS_Solid solid, TopoDS_Shape shell ) { this->solid = solid; if(IsReversed(this->solid)) { this->solid.Reverse(); } this->shell = shell; isDone = false; cutPoint = gp_Pnt(0, 0, 0); } void CutSolidAlgo::SetCutPoint(gp_Pnt p) { this->cutPoint = p; } TopoDS_Shape CutSolidAlgo::CutSurfaceBySolid(TopoDS_Shape& surf,TopoDS_Shape& solid2) { TopoDS_Shape TopoShape; TopoDS_Shape toposrf = surf; TopoDS_Shape toposld = solid2; vector faceIn,faceOut, faceOn; SplitShell(toposrf, toposld, faceIn, faceOut,faceOn); TopoDS_Compound c; BRep_Builder b; b.MakeCompound(c); for(int i = 0; i < faceIn.size(); i++) { b.Add(c, faceIn[i]); } for(int i = 0; i < faceOn.size(); i++) { b.Add(c, faceOn[i]); } TopoShape = c; return TopoShape; } TopoDS_Shape CutSolidAlgo::SplitShell(TopoDS_Shape& solid1,TopoDS_Shape& solid2, vector& faceIn, vector& faceOut, vector& faceOn) { TopoDS_Shape TopoShape,TopoTemp; TopoDS_Shell TopoShell; TopExp_Explorer ex,ex1; //BRepOffsetAPI_Sewing sew; BRepClass3d_SolidClassifier solidClassifier(TopoDS::Solid(this->solid)); int count = 0; BRep_Builder b; b.MakeShell(TopoShell); double areas = 0.0; vector pntSet; vector areaSet; Bnd_Box shellBox; static int hhh = 0; hhh++; //if(3==hhh) //{ // throw solid2; //} bool isSurf = (solid2.ShapeType() == TopAbs_FACE || solid2.ShapeType() == TopAbs_SHELL); for(TopExp_Explorer ex(solid2,TopAbs_FACE); ex.More(); ex.Next()) { TopoDS_Face face = TopoDS::Face(ex.Current()); GProp_GProps System_; gp_Pnt faceCenter; BRepGProp::SurfaceProperties(face,System_); faceCenter = System_.CentreOfMass(); double area = System_.Mass(); pntSet.push_back(faceCenter); areaSet.push_back(area); areas += area; } gp_Pnt solidCenter(0,0,0); for(int i = 0; i < pntSet.size(); i++) { gp_Pnt g1 = pntSet[i]; solidCenter.SetX(solidCenter.X() + g1.X() * areaSet[i] / areas); solidCenter.SetY(solidCenter.Y() + g1.Y() * areaSet[i] / areas); solidCenter.SetZ(solidCenter.Z() + g1.Z() * areaSet[i] / areas); } //return TopoTemp; for(TopExp_Explorer ex(solid2,TopAbs_FACE); ex.More(); ex.Next()) { b.Add(TopoShell,TopoDS::Face(ex.Current())); } //throw TopoShell; TopoTemp = TopoShell; TopoShape = TopoTemp; for(TopExp_Explorer ex(TopoTemp,TopAbs_VERTEX); ex.More(); ex.Next()) { gp_Pnt p = BRep_Tool::Pnt(TopoDS::Vertex(ex.Current())); shellBox.Add(p); } //return TopoTemp; vector shellSet; CutSurfaceAlgo cutSurface(solid1, TopoTemp); cutSurface.TrimSurfaceTranslateInsec(shellSet); vector faceSet; for(int i = 0; i < shellSet.size(); i++) { TopoDS_Shell shelltmp = shellSet[i]; for(TopExp_Explorer ex(shelltmp, TopAbs_FACE); ex.More(); ex.Next()) { faceSet.push_back(TopoDS::Face(ex.Current())); } } for(int i = 0; i < faceSet.size(); i++) { TopoDS_Face facetmp = faceSet[i]; vector vs,vs_center; GProp_GProps System; gp_Pnt faceCenter; BRepGProp::SurfaceProperties(facetmp,System); faceCenter = System.CentreOfMass(); for(TopExp_Explorer ex_f(facetmp, TopAbs_EDGE); ex_f.More(); ex_f.Next()) { TopoDS_Edge edge = TopoDS::Edge(ex_f.Current()); gp_Pnt p1,p2; GetEdgeStartEndPoint(edge, p1, p2); vs.push_back(p1); vs.push_back(p2); //for(TopExp_Explorer e_t(solid1, TopAbs_EDGE);e_t.More(); e_t.Next()) //{ // TopoDS_Edge edgeTmp = TopoDS::Edge(e_t.Current()); // if(CheckTwoEdgeOverlapByLinePointProject(edgeTmp, edge)) // { // double dl,df; // Handle(Geom_Curve) cv = BRep_Tool::Curve(edge, df,dl); // vs_center.push_back(cv->Value((df+dl) / 2)); // break; // } //} double dl,df; Handle(Geom_Curve) cv = BRep_Tool::Curve(edge, df,dl); vs_center.push_back(cv->Value((df+dl) / 2)); } bool isOn = true; bool isIn = false; int ik = 0; //pj change i->ik 内外层使用相同的i报错 //isIn = !isSurf; gp_Pnt ppp; for(ik = 0; ik < vs.size(); ik++) { TopoDS_Vertex v = BRepBuilderAPI_MakeVertex(vs[ik]); if(isOn) { BRepExtrema_DistShapeShape inter(v,TopoTemp); inter.Perform(); if(inter.Value() < Precision::Confusion()*100) { continue; } } ppp = vs[ik]; isOn = false; break; } if(isOn) { BRepExtrema_DistShapeShape inter(BRepBuilderAPI_MakeVertex(faceCenter).Vertex(),TopoTemp); inter.Perform(); if(inter.Value() > Precision::Confusion()*100) { isOn = false; //isIn = true; } if(!isOn) { isIn = true; for(int i = 0; i < vs_center.size(); i++) { solidClassifier.Perform(vs_center[i], 1E-3) ; TopAbs_State state = solidClassifier.State() ; if(state == TopAbs_OUT || state == TopAbs_UNKNOWN) { isIn = false; break; } } } } else { isIn = true; solidClassifier.Perform(ppp, 1E-3) ; TopAbs_State state = solidClassifier.State() ; if(state == TopAbs_OUT || state == TopAbs_UNKNOWN) { isIn = false; } } //if(!isOn) //{ // isIn = true; // for(int i = 0; i < vs_center.size(); i++) // { // solidClassifier.Perform(vs_center[i], 1E-5) ; // TopAbs_State state = solidClassifier.State() ; // if(state == TopAbs_OUT || state == TopAbs_UNKNOWN) // { // isIn = false; // break; // } // } //} if(isOn) { faceOn.push_back(facetmp); } else if(isIn) { faceIn.push_back(facetmp); } else { faceOut.push_back(facetmp); } } return TopoShape; } void CutSolidAlgo::Perform() { TopoDS_Shape splitface; vector shellSet; vector splitShellSet; vector solidSet; splitface = CutSurfaceBySolid(this->shell, this->solid); splitShellSet = SplitShapeToShell(splitface); CutSurfaceAlgo cutSurface(this->solid,this->shell); cutSurface.flag = this->flag; cutSurface.TrimSurfaceTranslateInsec(shellSet); if(shellSet.size() == 1) { throw shellSet[0]; return ; } //for(int i = 0; i < shellSet.size(); i++) //{ // BRepOffsetAPI_Sewing sewtmp; // sewtmp.Add(shell); // sewtmp.Add(shellSet[i]); // sewtmp.Perform(); // TopoDS_Shell shelltmp = TopoDS::Shell(sewtmp.SewedShape()); // solidSet.push_back(BRepBuilderAPI_MakeSolid(shelltmp).Solid()); //} for(int i = 0; i < shellSet.size(); i++) { TopoDS_Shell shelltmp; vector shapeSet; BRep_Builder bbb; bbb.MakeShell(shelltmp); try { //shapeSet.push_back(shellSet[i]); for(TopExp_Explorer ex(shellSet[i], TopAbs_FACE);ex.More();ex.Next()) { shapeSet.push_back(ex.Current()); } for(int j = 0; j < splitShellSet.size(); j++) { if(!IsConnect(shellSet[i], splitShellSet[j])) { continue; } //shapeSet.push_back(splitShellSet[j]); for(TopExp_Explorer ex(splitShellSet[j], TopAbs_FACE);ex.More();ex.Next()) { shapeSet.push_back(ex.Current()); } } //for(int ii = 0;ii < shapeSet.size(); ii++) //{ // for(TopExp_Explorer ex(shapeSet[ii], TopAbs_FACE);ex.More();ex.Next()) // { // bbb.Add(shelltmp, TopoDS::Face(ex.Current())); // } //} //throw shelltmp; //shapeSet.clear(); //shapeSet.push_back(shelltmp); //shapeSet = SolidSurfaceClear(shapeSet); shelltmp = SewShell(shapeSet); TopoDS_Solid s = BRepBuilderAPI_MakeSolid(shelltmp).Solid(); s.Closed(true); solidSet.push_back(s); } catch (Standard_Failure) { throw shelltmp; } } vector solids; //形心法判断去留,失败 for(int i = 0; i < (int)solidSet.size(); i++) { bool isSave = true; GProp_GProps System; gp_Pnt G1; BRepGProp::VolumeProperties(solidSet[i],System); G1 = System.CentreOfMass (); for(TopExp_Explorer ex(solidSet[i], TopAbs_FACE); ex.More(); ex.Next()) { TopoDS_Face face = TopoDS::Face(ex.Current()); BRepExtrema_DistShapeShape dis(BRepBuilderAPI_MakeVertex(this->cutPoint), face); dis.Perform(); if(dis.Value() < Precision::Confusion()) { solids.push_back(solidSet[i]); isSave = false; break; } } if(!isSave) { continue; } double V = abs(System.Mass()); //获取判断点集合,体中心和边的顶点 vector pSet; pSet.push_back(G1); for(TopExp_Explorer ex(solidSet[i], TopAbs_EDGE); ex.More();ex.Next()) { TopoDS_Edge edge = TopoDS::Edge(ex.Current()); gp_Pnt p1, p2; GetEdgeStartEndPoint(edge, p1,p2); pSet.push_back(p1); pSet.push_back(p2); } for(int j = 0; j < pSet.size(); j++) { TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(this->cutPoint, pSet[j]); BRepExtrema_DistShapeShape inter(edge,this->shell); inter.Perform(); //有交点 if(inter.Value() < Precision::Confusion() * 100) { gp_Pnt p = inter.PointOnShape1(1); //交点是线的端点,正常线 if(p.Distance(pSet[j]) < Precision::Confusion() * 100) { continue; } isSave = false; break; } } if(isSave) { solids.push_back(solidSet[i]); } }//形心法判断去留,失败 TopoDS_Compound c; BRep_Builder b; b.MakeCompound(c); for(int i = 0; i < solids.size(); i++) { b.Add(c, solids[i]); } this->result = c; isDone = true; } TopoDS_Shape CutSolidAlgo::GetResult() { TopoDS_Shape shape; if(isDone) { shape = this->result; } return shape; }