442 lines
9.3 KiB
C++
442 lines
9.3 KiB
C++
|
#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<TopoDS_Face> 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<TopoDS_Face>& faceIn, vector<TopoDS_Face>& faceOut, vector<TopoDS_Face>& 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<gp_Pnt> pntSet;
|
||
|
vector<double> 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<TopoDS_Shell> shellSet;
|
||
|
CutSurfaceAlgo cutSurface(solid1, TopoTemp);
|
||
|
cutSurface.TrimSurfaceTranslateInsec(shellSet);
|
||
|
|
||
|
vector<TopoDS_Face> 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<gp_Pnt> 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<TopoDS_Shell> shellSet;
|
||
|
vector<TopoDS_Shell> splitShellSet;
|
||
|
vector<TopoDS_Solid> 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<TopoDS_Shape> 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<TopoDS_Solid> 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<gp_Pnt> 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;
|
||
|
}
|