COMPASSi/trunk/code/projects/OCC/OCCLib/CutSolidAlgo.cpp

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;
}