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

2357 lines
56 KiB
C++
Raw Permalink Normal View History

2025-06-25 15:06:42 +08:00
#include "Stdafx.h"
#include "OCCCabin_Bool.h"
#include "OCCLib.h"
#include "SolidBool.h"
#include "BRepAlgoAPI_Section.hxx"
#include "BRepAlgoAPI_Common.hxx"
#include "BRepBuilderAPI_Copy.hxx"
#include "BRepBndLib.hxx"
#include "OCCCabin.h"
// Added BY XUEFENG
// 用于计算边对应该边所在面的PCurve
#include "ShapeConstruct_ProjectCurveOnSurface.hxx"
#include "GeomConvert.hxx" // XUEFENG ADDED 202009
#include "Geom_Surface.hxx" // XUEFENG ADDED 202009
#include "Geom_BSplineSurface.hxx" // XUEFENG ADDED 202009
#include "TopoDS_Shape.hxx"
#include <string> // ADDED BY XUEFENG 202012
using namespace std; // ADDED BY XUEFENG 202012
OCCCabin_Bool::OCCCabin_Bool(TopoDS_Shape solid)
{
this->solid = solid;
SetWidth(40);
SetHeight(40);
SetDir(DIR_X);
}
OCCCabin_Bool::~OCCCabin_Bool(void)
{
}
void OCCCabin_Bool::SetWidth( double width )
{
this->width = width;
}
void OCCCabin_Bool::SetHeight( double height )
{
this->height = height;
}
void OCCCabin_Bool::SetDir( DIR d )
{
this->dir = d;
}
void OCCCabin_Bool::Perform(Space space)
{
OCCLib occLib;
clock_t start,finish; //typedef long clock_t;
double totaltime;
start=clock(); //clock():确定处理器当前时间
// XUEFENG ADDED 202012
if(space.numSections>=1)
{
//this->MultiSectionSurface()
int realSections = space.numSections-1;
int numPoints = 0;
int count = 0;
while(space.FCharacterPoints[count]<999.9)
{
count++;
}
if(count%2!=0)
return;
int coupleNum = count/2;
if(coupleNum%space.numSections!=0)
return;
int sectionPointsNum = coupleNum/space.numSections;
TopoDS_Shape wholeShape;
for(int i=0;i<space.numSections-1;i++)
{
double frontPoints[MAX_ARRAY_SIZE_L];
double backpoints[MAX_ARRAY_SIZE_L];
memset(frontPoints, 0, MAX_ARRAY_SIZE_L);
memset(backpoints, 0, MAX_ARRAY_SIZE_L);
/*
for(int j=0; j<2*sectionPointsNum+2; j++)
{
frontPoints[j] = space.FCharacterPoints[i*2*sectionPointsNum + j];
backpoints[j] = space.FCharacterPoints[(i+1)*2*sectionPointsNum + j];
}
frontPoints[2*sectionPointsNum]= space.FCharacterPoints[i*2*sectionPointsNum + 0];
backpoints[2*sectionPointsNum] = space.FCharacterPoints[(i+1)*2*sectionPointsNum + 0];
frontPoints[2*sectionPointsNum+1]= space.FCharacterPoints[i*2*sectionPointsNum + 1];
backpoints[2*sectionPointsNum+1] = space.FCharacterPoints[(i+1)*2*sectionPointsNum + 1];
frontPoints[2*sectionPointsNum+2]=1000;
backpoints[2*sectionPointsNum+2]=1000;
vector<gp_Pnt2d> p2dSetFront = ConvertPoint2dSet(frontPoints, width, height);
vector<gp_Pnt2d> p2dSetBack = ConvertPoint2dSet(backpoints, width, height);
if(p2dSetBack.size() == 0 || p2dSetFront.size() == 0)
{
return;
}
vector<gp_Pnt> pSetFront = CreatePointSet(p2dSetFront, space.LCharacterPoints[i]);
vector<gp_Pnt> pSetBack = CreatePointSet(p2dSetBack, space.LCharacterPoints[i+1]);
*/
// XUEFENG MODIFIED 20210623
vector<gp_Pnt> pSetFront;
vector<gp_Pnt> pSetBack;
if(sectionPointsNum>2)
{
for(int j=0; j<2*sectionPointsNum; j++)
{
frontPoints[j] = space.FCharacterPoints[i*2*sectionPointsNum + j];
backpoints[j] = space.FCharacterPoints[(i+1)*2*sectionPointsNum + j];
}
/* // XUEFENG DELETED 20210623
frontPoints[2*sectionPointsNum]= space.FCharacterPoints[i*2*sectionPointsNum + 0];
backpoints[2*sectionPointsNum] = space.FCharacterPoints[(i+1)*2*sectionPointsNum + 0];
frontPoints[2*sectionPointsNum+1]= space.FCharacterPoints[i*2*sectionPointsNum + 1];
backpoints[2*sectionPointsNum+1] = space.FCharacterPoints[(i+1)*2*sectionPointsNum + 1];
*/
frontPoints[2*sectionPointsNum]=1000;
backpoints[2*sectionPointsNum]=1000;
vector<gp_Pnt2d> p2dSetFront = ConvertPoint2dSet(frontPoints, width, height);
vector<gp_Pnt2d> p2dSetBack = ConvertPoint2dSet(backpoints, width, height);
if(p2dSetBack.size() == 0 || p2dSetFront.size() == 0)
{
return;
}
//vector<gp_Pnt> pSetFront = CreatePointSet(p2dSetFront, space.LCharacterPoints[i]);
//vector<gp_Pnt> pSetBack = CreatePointSet(p2dSetBack, space.LCharacterPoints[i+1]);
pSetFront = CreatePointSet(p2dSetFront, space.LCharacterPoints[i]);
pSetBack = CreatePointSet(p2dSetBack, space.LCharacterPoints[i+1]);
// XUEFENG ADDED 20211020
gp_Pnt tmpCycleFPoint = pSetFront[0];
gp_Pnt tmpCycleBPoint = pSetBack[0];
pSetFront.push_back(tmpCycleFPoint);
pSetBack.push_back(tmpCycleBPoint);
// END ADDED
}
else if(sectionPointsNum==2)
{
for(int j=0; j<2*sectionPointsNum; j++)
{
frontPoints[j] = space.FCharacterPoints[i*2*sectionPointsNum + j];
backpoints[j] = space.FCharacterPoints[(i+1)*2*sectionPointsNum + j];
}
frontPoints[2*sectionPointsNum]=1000;
backpoints[2*sectionPointsNum]=1000;
vector<gp_Pnt2d> p2dSetFront = ConvertPoint2dSet(frontPoints, width, height);
vector<gp_Pnt2d> p2dSetBack = ConvertPoint2dSet(backpoints, width, height);
if(p2dSetBack.size() == 0 || p2dSetFront.size() == 0)
{
return;
}
pSetFront = CreatePointSet(p2dSetFront, space.LCharacterPoints[i]);
pSetBack = CreatePointSet(p2dSetBack, space.LCharacterPoints[i+1]);
}
else
return;
// END MODIFIED
TopoDS_Shape sectionShape = this->ConstructComplexBSplineShape(pSetFront, pSetBack);
{
GProp_GProps massProps;
BRepGProp::VolumeProperties(sectionShape, massProps);
Standard_Real myVolume = massProps.Mass();
if(myVolume<0)
sectionShape.Reverse();
}
if(wholeShape.IsNull()==true)
wholeShape = sectionShape;
else
{
BRepAlgoAPI_Fuse boolOper(wholeShape,sectionShape);
if(boolOper.IsDone())
{
wholeShape = boolOper.Shape();
}
}
}
// XUEFENG ADDED 20230509
// FOR DEBUG
{
GProp_GProps massProps;
BRepGProp::VolumeProperties(wholeShape, massProps);
Standard_Real myVolume = massProps.Mass();
if(myVolume<0)
wholeShape.Reverse();
}
result = wholeShape;
if(space.HullID==-99999) // FROM 0
{
result = wholeShape;
return;
}
//船体
TopoDS_Shape solidHULL = this->solid; //XUEFENG ADDED 20210623
{
GProp_GProps massProps;
BRepGProp::VolumeProperties(solidHULL, massProps);
Standard_Real myVolume = massProps.Mass();
if(myVolume<0)
solidHULL.Reverse();
}
TopoDS_Shape S;
BRepAlgoAPI_Common boolOper(solidHULL,wholeShape);
if(boolOper.IsDone())
{
S = boolOper.Shape();
result = S;
return;
}
return;
}
// END ADDED
if(space.X1 > space.X2) //尾端面应小于首端面
{
return;
}
//体
TopoDS_Shape solid1 = this->solid;
//BRepTools::Write(solid1, "C:\\CCS\\doc\\CabinError\\ComplexHull.brep");
//前后位置面
TopoDS_Face faceFront,faceBack;
vector<gp_Pnt> borderFront,borderBack;
switch(dir)
{
case DIR_X:
faceFront = occLib.CreatePlane(space.X1, PlaneX, width, height);
faceBack = occLib.CreatePlane(space.X2, PlaneX, width, height);
borderFront.push_back(gp_Pnt(space.X1, width / 2, height / 2));
borderFront.push_back(gp_Pnt(space.X1, -1 * width / 2, height / 2));
borderFront.push_back(gp_Pnt(space.X1, -1 * width / 2, -1 * height / 2));
borderFront.push_back(gp_Pnt(space.X1, width / 2, -1 * height / 2));
borderFront.push_back(gp_Pnt(space.X1, width / 2, height / 2));
borderBack.push_back(gp_Pnt(space.X2, width / 2, height / 2));
borderBack.push_back(gp_Pnt(space.X2, -1 * width / 2, height / 2));
borderBack.push_back(gp_Pnt(space.X2, -1 * width / 2, -1 * height / 2));
borderBack.push_back(gp_Pnt(space.X2, width / 2, -1 * height / 2));
borderBack.push_back(gp_Pnt(space.X2, width / 2, height / 2));
break;
case DIR_Y:
faceFront = occLib.CreatePlane(space.X1, PlaneY, width, height);
faceBack = occLib.CreatePlane(space.X2, PlaneY, width, height);
borderFront.push_back(gp_Pnt( width / 2, space.X1, height / 2));
borderFront.push_back(gp_Pnt(-1 * width / 2, space.X1, height / 2));
borderFront.push_back(gp_Pnt( -1 * width / 2, space.X1, -1 * height / 2));
borderFront.push_back(gp_Pnt( width / 2, space.X1, -1 * height / 2));
borderFront.push_back(gp_Pnt(width / 2, space.X1, height / 2));
borderBack.push_back(gp_Pnt(width / 2, space.X2, height / 2));
borderBack.push_back(gp_Pnt( -1 * width / 2, space.X2, height / 2));
borderBack.push_back(gp_Pnt(-1 * width / 2, space.X2, -1 * height / 2));
borderBack.push_back(gp_Pnt( width / 2, space.X2, -1 * height / 2));
borderBack.push_back(gp_Pnt( width / 2, space.X2, height / 2));
break;
case DIR_Z:
faceFront = occLib.CreatePlane(space.X1, PlaneZ, width, height);
faceBack = occLib.CreatePlane(space.X2, PlaneZ, width, height);
borderFront.push_back(gp_Pnt(width / 2, height / 2, space.X1));
borderFront.push_back(gp_Pnt(-1 * width / 2, height / 2, space.X1));
borderFront.push_back(gp_Pnt( -1 * width / 2, -1 * height / 2, space.X1));
borderFront.push_back(gp_Pnt( width / 2, -1 * height / 2, space.X1));
borderFront.push_back(gp_Pnt( width / 2, height / 2, space.X1));
borderBack.push_back(gp_Pnt(width / 2, height / 2, space.X2));
borderBack.push_back(gp_Pnt( -1 * width / 2, height / 2, space.X2));
borderBack.push_back(gp_Pnt(-1 * width / 2, -1 * height / 2, space.X2));
borderBack.push_back(gp_Pnt( width / 2, -1 * height / 2, space.X2));
borderBack.push_back(gp_Pnt(width / 2, height / 2, space.X2));
break;
default:
return;
}
//剪切面
TopoDS_Shell splitShell;
vector<gp_Pnt2d> p2dSetFront = ConvertPoint2dSet(space.FCharacterPoints, width, height);
vector<gp_Pnt2d> p2dSetBack = ConvertPoint2dSet(space.LCharacterPoints, width, height);
if(p2dSetBack.size() == 0 || p2dSetFront.size() == 0)
{
return;
}
vector<gp_Pnt> pSetFront = CreatePointSet(p2dSetFront, space.X1);
vector<gp_Pnt> pSetBack = CreatePointSet(p2dSetBack, space.X2);
// Added BY XUEFENG 2018.03
// 根据前后断面的特征点按OCC的拓扑结构要求构造一个立方体用该立方体和原船体进行布尔操作
// 根据特征点构造的立方体的前后断面为平面侧面按B样条曲面进行构造。
TopoDS_Shape trunctShape = this->ConstructComplexBSplineShape(pSetFront, pSetBack);
// ADDED BY XUEFENG 202012
if(space.HullID==-99999) // FROM 0
{
result = trunctShape;
return;
}
// END ADDED
// 求体积
// 体积为负一般意味着体的方向错了,需要进行反向
// Added BY XUEFENG 2018.03
{
GProp_GProps massProps;
BRepGProp::VolumeProperties(solid1, massProps);
Standard_Real myVolume = massProps.Mass();
if(myVolume<0)
solid1.Reverse();
}
// End Added
TopoDS_Shape S;
BRepAlgoAPI_Common boolOper(solid1,trunctShape);
if(boolOper.IsDone())
{
S = boolOper.Shape();
result = S;
return;
}
//
// End ADDED
int countBorderF = 0, countBorderB = 0;
for(int j = 0; j < pSetFront.size(); j++)
{
gp_Pnt p = pSetFront[j];
bool isborderF = false;
for(int i = 0; i < borderFront.size() - 1; i++)
{
if(p.Distance(borderFront[i]) < Precision::Confusion())
{
isborderF = true;
break;
}
}
if(isborderF)
{
countBorderF++;
}
}
for(int j = 0; j < pSetBack.size(); j++)
{
gp_Pnt p = pSetBack[j];
bool isborderB = false;
for(int i = 0; i < borderBack.size() - 1; i++)
{
if(p.Distance(borderBack[i]) < Precision::Confusion())
{
isborderB = true;
break;
}
}
if(isborderB)
{
countBorderB++;
}
}
splitShell = CreateSplitShell(pSetFront, pSetBack);
//throw splitShell;
//剪切端面
//TopoDS_Face frontFace = CreateEndFace( pSetFront , width, height, space.X1);
//TopoDS_Face backFace = CreateEndFace( pSetBack, width, height, space.X2);
TopoDS_Face frontFace = CutEndFace(faceFront, splitShell, pSetFront, false);// 生成面的时候 边的方向与输入方向是反的
TopoDS_Face backFace = CutEndFace(faceBack, splitShell, pSetBack, false);
//result = backFace;
//return;
//创建体
vector<TopoDS_Shape> shapeSet;
shapeSet.push_back(splitShell);
shapeSet.push_back(frontFace);
shapeSet.push_back(backFace);
//TopoDS_Compound c;
//BRep_Builder b;
//b.MakeCompound(c);
//b.Add(c,splitShell);
//b.Add(c,frontFace);
//b.Add(c,backFace);
//throw c;
int count = 0;
for(int i = 0; i < borderFront.size() - 1; i++)
{
BRepExtrema_DistShapeShape dis(BRepBuilderAPI_MakeVertex(borderFront[i]), frontFace);
dis.Perform();
if(dis.Value() < Precision::Confusion())
{
count++;
}
}
if(count == 4 && !(countBorderB == pSetBack.size() && countBorderF == pSetFront.size()))
{
TopoDS_Shell borderShell = CreateSplitShell(borderFront, borderBack);
shapeSet.push_back(borderShell);
}
TopoDS_Shell shell = occLib.SewShell(shapeSet);
TopoDS_Solid solid2 = BRepBuilderAPI_MakeSolid(shell).Solid();
if(IsReversed(solid2))
{
solid2.Reverse();
}
if(IsReversed(solid1))
{
solid1.Reverse();
}
//throw solid2;
//BRepAlgoAPI_Common common(solid1 ,shell);
//throw common.Shape();
//BRepAlgoAPI_Section asect(solid1,shell,Standard_False);
//asect.ComputePCurveOn1(Standard_True);
////asect.ComputePCurveOn2(Standard_True);
//asect.Approximation(Standard_True);
//asect.Build();
//throw asect.Shape();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
//finish=clock();
//totaltime=(double)(finish-start)/CLOCKS_PER_SEC;
//cout << "+++++++++++++++++++++++++++++++准备工作:"<<totaltime<<"s"<<endl;
//SolidBool solidBool(solid1, solid2, BOOL_COMMON);
//solidBool.Perform();
//result = solidBool.GetResult();
////////////////////////////////////////////////////////////////////////////////////////
//throw solid2;
TopoDS_Shell borderShell = CreateSplitShell(borderFront, borderBack);
shapeSet.clear();
shapeSet.push_back(borderShell);
shapeSet.push_back(faceFront);
shapeSet.push_back(faceBack);
TopoDS_Shell shell3 = occLib.SewShell(shapeSet);
TopoDS_Solid solid3 = BRepBuilderAPI_MakeSolid(shell3);
//result = solid2;
//return;
//BRepTools::Write(solid, "C:\\solid1.brep");
//BRepTools::Write(solid2, "C:\\solid2.brep");
OCCCabin occCabin(solid, faceFront, faceBack, splitShell, gp_Pnt(0,0,0));
occCabin.SetSecondSolid(solid2);
occCabin.SetThirdSolid(solid3);
occCabin.Build();
result = occCabin.GetResult();
//TopoDS_Compound c;
//BRep_Builder b;
//b.MakeCompound(c);
//b.Add(c, solid);
//b.Add(c, solid2);
//BRepTools::Write(c, "C:\\ttt.brep");
//result = solid2;
}
TopoDS_Shape OCCCabin_Bool::ConstructComplexBSplineShape(std::vector<gp_Pnt> pSetFront,std::vector<gp_Pnt> pSetBack)
{
// XUEFENG MODIFIED MANY MANY 202012
// This method only choose which way to use
// Triangle face use 7.1.0, normal use 6.3.0
bool triangleFace=false;
Standard_Real myTol = Precision::Confusion();
int pointNum = pSetFront.size();
for(int i=0;i<pointNum-2;i++)
{
if( pSetFront[i].SquareDistance( pSetFront[i+1]) <= myTol)
triangleFace = true;
if( pSetBack[i].SquareDistance( pSetBack[i+1]) <= myTol)
triangleFace = true;
}
if(triangleFace)
return ConstructComplexBSplineShape710(pSetFront, pSetBack);
else
return ConstructComplexBSplineShape630Original(pSetFront, pSetBack);
}
// 下面开始实现
// Handle(Geom2d_Curve) getPCurve(Handle(Geom_Surface) surfaceIn, Handle(Geom_Curve) curve3dIn)
// TopoDS_Shape ConstructComplexBSplineShape(std::vector<gp_Pnt> pSetFront,std::vector<gp_Pnt> pSetBack)
// Handle(Geom_BSplineCurve) getBSplineCurveMultiPoints(gp_Pnt points[], int len)
// 3个函数
/*
*
*/
// XUEFENG ADDED 202102
// FOR CONSTRUCT SOLID in OCC 6.3.0 and 7.1.0 WAY
// This is a 7.1.0 way!
TopoDS_Shape OCCCabin_Bool::ConstructComplexBSplineShape710(std::vector<gp_Pnt> pSetFront,std::vector<gp_Pnt> pSetBack)
{
// XUEFENG MODIFIED MANY MANY 202012
TopoDS_Solid mySolid;
TopoDS_Shell myShell;
BRep_Builder myBrepBuilder;
Standard_Real myTol = Precision::Confusion();
myBrepBuilder.MakeShell(myShell);
myBrepBuilder.MakeSolid(mySolid);
std::vector<TopoDS_Vertex> frontVertex, backVertex;
std::vector<Handle(Geom_BSplineCurve)> frontBSplineLine, backBSplineLine, sideBSplineLine;
std::vector<TopoDS_Edge> frontBSplineEdge, backBSplineEdge, sideBSplineEdge;
int pointNum = pSetFront.size();
for(int i=0;i<pointNum-1;i++)
{
TopoDS_Vertex fV,bV;
myBrepBuilder.MakeVertex(fV, pSetFront[i], myTol);
myBrepBuilder.MakeVertex(bV, pSetBack[i], myTol);
frontVertex.push_back(fV);
backVertex.push_back(bV);
}
// Init Geom_Curve3ds
// 构建前、后、侧面的 几何几何几何 边
for(int i=0;i<pointNum-1;i++)
{
int next = (i==(pointNum-2))? 0:(i+1);
{
gp_Pnt pointsArray[2] = { pSetFront[i], pSetFront[next] };
Handle(Geom_BSplineCurve) frontBSPL = NULL;
if( pSetFront[i].SquareDistance( pSetFront[next]) > myTol)
frontBSPL = getBSplineCurveMultiPoints(pointsArray, 2);
frontBSplineLine.push_back(frontBSPL);
}
{
gp_Pnt pointsArray[2] = { pSetBack[i], pSetBack[next] };
Handle(Geom_BSplineCurve) backBSPL = NULL;
if( pSetBack[i].SquareDistance( pSetBack[next]) > myTol)
backBSPL = getBSplineCurveMultiPoints(pointsArray, 2);
backBSplineLine.push_back(backBSPL);
}
{
gp_Pnt pointsArray[2] = { pSetFront[i], pSetBack[i] };
Handle(Geom_BSplineCurve) sideBSPL = getBSplineCurveMultiPoints(pointsArray, 2);
sideBSplineLine.push_back(sideBSPL);
}
}
// Init edges
// 构建前、后、侧面的 拓扑拓扑拓扑 边
for(int i=0;i<pointNum-1;i++)
{
int next = (i==(pointNum-2))? 0:(i+1);
// Front BSpline Edge
TopoDS_Edge fBSplineEdge;
Handle(Geom_Curve) frontCurve = frontBSplineLine[i];
if(!frontCurve.IsNull()) //pj change !=NULL->!.IsNull()
{
myBrepBuilder.MakeEdge(fBSplineEdge, frontCurve, Precision::Confusion());
{
TopoDS_Vertex bV = frontVertex[i];
TopoDS_Vertex eV = frontVertex[next];
bV.Orientation(TopAbs_FORWARD);
eV.Orientation(TopAbs_REVERSED);
myBrepBuilder.Add(fBSplineEdge, bV);
myBrepBuilder.Add(fBSplineEdge, eV);
BRepTools::Update(fBSplineEdge);
}
}
if(fBSplineEdge.IsNull())
int stop = 10;
frontBSplineEdge.push_back(fBSplineEdge);
// Back BSpline Edge
TopoDS_Edge bBSplineEdge;
Handle(Geom_Curve) backCurve = backBSplineLine[i];
if(!backCurve.IsNull()) //pj change !=NULL->!.IsNull()
{
myBrepBuilder.MakeEdge(bBSplineEdge, backCurve, Precision::Confusion());
{
TopoDS_Vertex bV = backVertex[i];
TopoDS_Vertex eV = backVertex[next];
bV.Orientation(TopAbs_FORWARD);
eV.Orientation(TopAbs_REVERSED);
myBrepBuilder.Add(bBSplineEdge, bV);
myBrepBuilder.Add(bBSplineEdge, eV);
BRepTools::Update(bBSplineEdge);
}
}
if(bBSplineEdge.IsNull())
int stop = 10;
backBSplineEdge.push_back(bBSplineEdge);
TopoDS_Edge sBSplineEdge;
Handle(Geom_Curve) sideCurve = sideBSplineLine[i];
myBrepBuilder.MakeEdge(sBSplineEdge, sideCurve, Precision::Confusion());
{
TopoDS_Vertex bV = frontVertex[i];
TopoDS_Vertex eV = backVertex[i];
bV.Orientation(TopAbs_FORWARD);
eV.Orientation(TopAbs_REVERSED);
myBrepBuilder.Add(sBSplineEdge, bV);
myBrepBuilder.Add(sBSplineEdge, eV);
BRepTools::Update(sBSplineEdge);
}
sideBSplineEdge.push_back(sBSplineEdge);
}
// XUEFENG ADDED 20201208
// OCC 7.1.0. Simple Way
TopoDS_Face frontFace,backFace;
std::vector<TopoDS_Face> sideFaces;
BRepBuilderAPI_Sewing mySewObj(Precision::Confusion());
{
// Front and Back face
TopoDS_Wire fWire,bWire;
myBrepBuilder.MakeWire(fWire);
myBrepBuilder.MakeWire(bWire);
for(int i=0;i<pointNum-1;i++)
{
if(!frontBSplineEdge[i].IsNull())
myBrepBuilder.Add(fWire, frontBSplineEdge[i]);
if(!backBSplineEdge[i].IsNull())
myBrepBuilder.Add(bWire, backBSplineEdge[i]);
}
BRepTools::Update(fWire);
BRepTools::Update(bWire);
Standard_Boolean retfW = fWire.Closed();
Standard_Boolean retbW = bWire.Closed();
//bWire.Reverse();
frontFace = BRepBuilderAPI_MakeFace(fWire, true);
backFace = BRepBuilderAPI_MakeFace(bWire, true);
}
mySewObj.Add(frontFace);
mySewObj.Add(backFace);
myBrepBuilder.Add(myShell,frontFace);
myBrepBuilder.Add(myShell,backFace);
//return myShell;
// 构建几何体的侧面
{
std::vector<TopoDS_Wire> sideWires;
for(int i=0;i<pointNum-1;i++)
{
int next = (i==(pointNum-2))? 0:(i+1);
TopoDS_Wire sWire;
/*
myBrepBuilder.MakeWire(sWire);
myBrepBuilder.Add(sWire, frontBSplineEdge[i]);
myBrepBuilder.Add(sWire, sideBSplineEdge[next]);
backBSplineEdge[i].Reverse();
sideBSplineEdge[i].Reverse();
myBrepBuilder.Add(sWire, backBSplineEdge[i]);
myBrepBuilder.Add(sWire, sideBSplineEdge[i]);
BRepTools::Update(sWire);
*/
{
GeomFill_FillingStyle fillType = GeomFill_StretchStyle;
Handle(Geom_BSplineCurve) GL1 = frontBSplineLine[i];
Handle(Geom_BSplineCurve) GL2 = sideBSplineLine[next];
Handle(Geom_BSplineCurve) GL3 = backBSplineLine[i];
Handle(Geom_BSplineCurve) GL4 = sideBSplineLine[i];
GeomFill_BSplineCurves aGeomFill;
/* if(GL1==NULL && GL2!=NULL && GL3!=NULL && GL4!=NULL) //pj change
aGeomFill.Init( GL2, GL3, GL4, fillType); // XUEFENG MODIFIED 202102 //pj change
else if(GL1!=NULL && GL2!=NULL && GL3==NULL && GL4!=NULL) //pj change
aGeomFill.Init(GL1, GL2, GL4, fillType);
else if(GL1==NULL && GL3==NULL) // XUEFENG MODIFIED 202102 NO face //pj change
continue; // XUEFENG MODIFIED 202102
else
aGeomFill.Init(GL1, GL2, GL3, GL4, fillType); */
if(GL1.IsNull() && !GL2.IsNull() && !GL3.IsNull() && !GL4.IsNull()) //pj change !=NULL->!.IsNull() ==NULL->.IsNull()
aGeomFill.Init( GL2, GL3, GL4, fillType); // XUEFENG MODIFIED 202102 //pj change
else if(!GL1.IsNull() && !GL2.IsNull() && GL3.IsNull() && !GL4.IsNull()) //pj change
aGeomFill.Init(GL1, GL2, GL4, fillType);
else if(GL1.IsNull() && GL3.IsNull()) // XUEFENG MODIFIED 202102 NO face //pj change
continue; // XUEFENG MODIFIED 202102
else
aGeomFill.Init(GL1, GL2, GL3, GL4, fillType);
Handle(Geom_BSplineSurface) aSurf = aGeomFill.Surface(); // XUEFENG ADDED 202009 OCC 7.1.0
TopoDS_Face sBSplineFace = BRepBuilderAPI_MakeFace(aSurf, Precision::Confusion()); // XUEFENG ADDED 202009
//backBSplineEdge[i].Reverse();
//sideBSplineEdge[i].Reverse();
//sideWires.push_back(sWire);
sideFaces.push_back(sBSplineFace);
mySewObj.Add(sBSplineFace);
}
}
}
mySewObj.Perform();
TopoDS_Shell mySewShell = TopoDS::Shell(mySewObj.SewedShape());
TopoDS_Solid mySewSolid = BRepBuilderAPI_MakeSolid(mySewShell);
// 求体积
// 体积为负一般意味着体的方向错了,需要进行反向
// Added BY XUEFENG 2018.03
{
GProp_GProps massProps;
BRepGProp::VolumeProperties(mySewSolid, massProps);
Standard_Real myVolume = massProps.Mass();
if(myVolume<0)
mySewSolid.Reverse();
}
// End Added
// END ADDED
return mySewSolid;
}
// This is a 6.3.0 Way!
TopoDS_Shape OCCCabin_Bool::ConstructComplexBSplineShape630Original(std::vector<gp_Pnt> pSetFront,std::vector<gp_Pnt> pSetBack)
{
TopoDS_Solid mySolid;
TopoDS_Shell myShell;
BRep_Builder myBrepBuilder;
Standard_Real myTol = Precision::Confusion();
myBrepBuilder.MakeShell(myShell);
myBrepBuilder.MakeSolid(mySolid);
std::vector<TopoDS_Vertex> frontVertex, backVertex;
std::vector<Handle(Geom_BSplineCurve)> frontBSplineLine, backBSplineLine, sideBSplineLine;
std::vector<TopoDS_Edge> frontBSplineEdge, backBSplineEdge, sideBSplineEdge;
// XUEFENG ADDED 20211020
/*
gp_Pnt tmpCycleFPoint = pSetFront[0];
gp_Pnt tmpCycleBPoint = pSetBack[0];
pSetFront.push_back(tmpCycleFPoint);
pSetBack.push_back(tmpCycleBPoint);
*/
// END ADDED
int pointNum = pSetFront.size();
for(int i=0;i<pointNum-1;i++)
{
TopoDS_Vertex fV,bV;
myBrepBuilder.MakeVertex(fV, pSetFront[i], myTol);
myBrepBuilder.MakeVertex(bV, pSetBack[i], myTol);
frontVertex.push_back(fV);
backVertex.push_back(bV);
}
// Init Geom_Curve3ds
// 构建前、后、侧面的 几何几何几何 边
for(int i=0;i<pointNum-1;i++)
{
int next = (i==(pointNum-2))? 0:(i+1);
{
gp_Pnt pointsArray[2] = { pSetFront[i], pSetFront[next] };
Handle(Geom_BSplineCurve) frontBSPL = getBSplineCurveMultiPoints(pointsArray, 2);
frontBSplineLine.push_back(frontBSPL);
}
{
gp_Pnt pointsArray[2] = { pSetBack[i], pSetBack[next] };
Handle(Geom_BSplineCurve) backBSPL = getBSplineCurveMultiPoints(pointsArray, 2);
backBSplineLine.push_back(backBSPL);
}
{
gp_Pnt pointsArray[2] = { pSetFront[i], pSetBack[i] };
Handle(Geom_BSplineCurve) sideBSPL = getBSplineCurveMultiPoints(pointsArray, 2);
sideBSplineLine.push_back(sideBSPL);
}
}
// Init edges
// 构建前、后、侧面的 拓扑拓扑拓扑 边
for(int i=0;i<pointNum-1;i++)
{
int next = (i==(pointNum-2))? 0:(i+1);
// Front BSpline Edge
TopoDS_Edge fBSplineEdge;
Handle(Geom_Curve) frontCurve = frontBSplineLine[i];
myBrepBuilder.MakeEdge(fBSplineEdge, frontCurve, Precision::Confusion());
{
TopoDS_Vertex bV = frontVertex[i];
TopoDS_Vertex eV = frontVertex[next];
bV.Orientation(TopAbs_FORWARD);
eV.Orientation(TopAbs_REVERSED);
myBrepBuilder.Add(fBSplineEdge, bV);
myBrepBuilder.Add(fBSplineEdge, eV);
BRepTools::Update(fBSplineEdge);
}
frontBSplineEdge.push_back(fBSplineEdge);
// Back BSpline Edge
TopoDS_Edge bBSplineEdge;
Handle(Geom_Curve) backCurve = backBSplineLine[i];
myBrepBuilder.MakeEdge(bBSplineEdge, backCurve, Precision::Confusion());
{
TopoDS_Vertex bV = backVertex[i];
TopoDS_Vertex eV = backVertex[next];
bV.Orientation(TopAbs_FORWARD);
eV.Orientation(TopAbs_REVERSED);
myBrepBuilder.Add(bBSplineEdge, bV);
myBrepBuilder.Add(bBSplineEdge, eV);
BRepTools::Update(bBSplineEdge);
}
backBSplineEdge.push_back(bBSplineEdge);
TopoDS_Edge sBSplineEdge;
Handle(Geom_Curve) sideCurve = sideBSplineLine[i];
myBrepBuilder.MakeEdge(sBSplineEdge, sideCurve, Precision::Confusion());
{
TopoDS_Vertex bV = frontVertex[i];
TopoDS_Vertex eV = backVertex[i];
bV.Orientation(TopAbs_FORWARD);
eV.Orientation(TopAbs_REVERSED);
myBrepBuilder.Add(sBSplineEdge, bV);
myBrepBuilder.Add(sBSplineEdge, eV);
BRepTools::Update(sBSplineEdge);
}
sideBSplineEdge.push_back(sBSplineEdge);
}
{
// Front and Back face
TopoDS_Wire fWire,bWire;
myBrepBuilder.MakeWire(fWire);
myBrepBuilder.MakeWire(bWire);
for(int i=0;i<pointNum-1;i++)
{
myBrepBuilder.Add(fWire, frontBSplineEdge[i]);
myBrepBuilder.Add(bWire, backBSplineEdge[i]);
}
BRepTools::Update(fWire);
BRepTools::Update(bWire);
Standard_Boolean retfW = fWire.Closed();
Standard_Boolean retbW = bWire.Closed();
// Construct face
{
TopoDS_Face frontFace,backFace;
/*
gp_Dir dirF1(pSetFront[0].X()-pSetFront[1].X(),
pSetFront[0].Y()-pSetFront[1].Y(),
pSetFront[0].Z()-pSetFront[1].Z());
gp_Dir dirF2(pSetFront[1].X()-pSetFront[2].X(),
pSetFront[1].Y()-pSetFront[2].Y(),
pSetFront[1].Z()-pSetFront[2].Z());
gp_Dir dirCrossF = dirF2.Crossed(dirF1);
gp_Pln fPlane(pSetFront[1],dirCrossF);
*/
gp_Pln fPlane(pSetFront[1],gp_Dir(1,0,0)); // 平面法向顺 X 轴方向,前断面后面要反向
myBrepBuilder.MakeFace(frontFace,new Geom_Plane(fPlane),Precision::Confusion());
/*
gp_Dir dirB1(pSetBack[1].X()-pSetBack[0].X(),
pSetBack[1].Y()-pSetBack[0].Y(),
pSetBack[1].Z()-pSetBack[0].Z());
gp_Dir dirB2(pSetBack[2].X()-pSetBack[1].X(),
pSetBack[2].Y()-pSetBack[1].Y(),
pSetBack[2].Z()-pSetBack[1].Z());
gp_Dir dirCrossB = dirB2.Crossed(dirB1);
gp_Pln bPlane(pSetBack[1],dirCrossB);
*/
gp_Pln bPlane(pSetBack[1],gp_Dir(1,0,0)); // 平面法向顺 X 轴方向,后断面保持
myBrepBuilder.MakeFace(backFace,new Geom_Plane(bPlane),Precision::Confusion());
myBrepBuilder.Add(frontFace, fWire);
myBrepBuilder.Add(backFace, bWire);
frontFace.Reverse(); // 这个面的朝向要反向,否则构建的体的这个面的朝向将不对,会导致布尔失败
myBrepBuilder.Add(myShell, frontFace);
myBrepBuilder.Add(myShell, backFace);
}
}
// 构建几何体的侧面
{
// Side faces
std::vector<TopoDS_Wire> sideWires;
std::vector<TopoDS_Face> sideFaces;
for(int i=0;i<pointNum-1;i++)
{
int next = (i==(pointNum-2))? 0:(i+1);
TopoDS_Wire sWire;
myBrepBuilder.MakeWire(sWire);
myBrepBuilder.Add(sWire, frontBSplineEdge[i]);
myBrepBuilder.Add(sWire, sideBSplineEdge[next]);
backBSplineEdge[i].Reverse();
sideBSplineEdge[i].Reverse();
myBrepBuilder.Add(sWire, backBSplineEdge[i]);
myBrepBuilder.Add(sWire, sideBSplineEdge[i]);
BRepTools::Update(sWire);
{
GeomFill_FillingStyle fillType = GeomFill_StretchStyle;
Handle(Geom_BSplineCurve) GL1 = frontBSplineLine[i];
Handle(Geom_BSplineCurve) GL2 = sideBSplineLine[next];
Handle(Geom_BSplineCurve) GL3 = backBSplineLine[i];
Handle(Geom_BSplineCurve) GL4 = sideBSplineLine[i];
GeomFill_BSplineCurves aGeomFill(GL1, GL2, GL3, GL4, fillType);
Handle(Geom_BSplineSurface) aBSplineSurface = aGeomFill.Surface();
Handle(Geom_Surface) aSurf = aBSplineSurface;
TopoDS_Face sBSplineFace;
BRepBuilderAPI_MakeFace MF;
MF.Init(aSurf, false, myTol); // OCC 7.1.0
//MF.Init(aSurf, false);
MF.Add(sWire);
sBSplineFace = MF.Face();
// 关键关键
// 添加边和面的投影关系信息
{
myBrepBuilder.UpdateEdge(frontBSplineEdge[i], this->getPCurve(aSurf, GL1), sBSplineFace, Precision::Confusion());
myBrepBuilder.UpdateEdge(sideBSplineEdge[next], this->getPCurve(aSurf, GL2), sBSplineFace, Precision::Confusion());
myBrepBuilder.UpdateEdge(backBSplineEdge[i], this->getPCurve(aSurf, GL3), sBSplineFace, Precision::Confusion());
myBrepBuilder.UpdateEdge(sideBSplineEdge[i], this->getPCurve(aSurf, GL4), sBSplineFace, Precision::Confusion());
BRepTools::Update(sBSplineFace);
}
backBSplineEdge[i].Reverse();
sideBSplineEdge[i].Reverse();
sideWires.push_back(sWire);
sideFaces.push_back(sBSplineFace);
myBrepBuilder.Add(myShell,sBSplineFace);
}
}
}
myBrepBuilder.Add(mySolid, myShell);
return mySolid;
}
// END ADDED
/*
* 线
* GeomAPI_PointsToBSpline
*/
Handle(Geom_BSplineCurve) OCCCabin_Bool::getBSplineCurveMultiPoints(gp_Pnt points[], int len)
{
/*
TColgp_Array1OfPnt SPLPoints(1,len);
for(int i=1;i<=len;i++)
SPLPoints(i)=points[i-1];
GeomAPI_PointsToBSpline aPointToSPL(SPLPoints);
Handle(Geom_BSplineCurve) SPL = aPointToSPL.Curve();
*/
Handle(TColgp_HArray1OfPnt) SPLPoints = new TColgp_HArray1OfPnt(1,len);
for(int i=1;i<=len;i++)
SPLPoints->SetValue(i, points[i-1]);
GeomAPI_Interpolate PtB(SPLPoints, Standard_False, 0.0);
PtB.Perform();
Handle(Geom_BSplineCurve) SPL;
if(PtB.IsDone())
SPL=PtB.Curve();
return SPL;
}
/**
* Get the pcurve from a curve on a surface
* 线线
*/
Handle(Geom2d_Curve) OCCCabin_Bool::getPCurve(Handle(Geom_Surface) surfaceIn, Handle(Geom_Curve) curve3dIn)
{
Handle(Geom2d_Curve) pcurve = NULL;
//try{
// ShapeConstruct_ProjectCurveOnSurface pCurveProjector;
// pCurveProjector.Init(surfaceIn, 0.0);
// Standard_Boolean success = pCurveProjector.PerformAdvanced(curve3dIn,
// curve3dIn->FirstParameter(),
// curve3dIn->LastParameter(),
// pcurve);
//}catch(...){
// Something error.
//}
return pcurve;
}
// 添加的3个函数实现部分结束
// BY XUEFENG 2018.03.10
//布尔运算 20170601 by czb,type: 0-并1-差2-交
TopoDS_Shape TopoSolidBrepAlgo(int type,TopoDS_Shape& solid1,TopoDS_Shape& solid2)
{
TopoDS_Shape toposhape;
if (solid1.IsNull() || solid2.IsNull()) return toposhape;
BaseAlgo algo;
if(algo.IsReversed((solid1)))
{
solid1.Reverse();
}
if(algo.IsReversed((solid2)))
{
solid2.Reverse();
}
try
{
if(type==0)//并
{
BRepAlgoAPI_Fuse newfuse(solid1 ,solid2);
if (!newfuse.IsDone())
{
return toposhape;
}
else
{
toposhape=newfuse.Shape();
}
}
else if(type==1)//差
{
BRepAlgoAPI_Cut cut(solid1, solid2);
if(!cut.IsDone())
{
return toposhape;
}
toposhape = cut.Shape();
}
else if(type==2)//交
{
BRepAlgoAPI_Common comm(solid1, solid2);
if(!comm.IsDone())
{
return toposhape;
}
toposhape = comm.Shape();
}
}
catch(...) //20170601 by czb防止出错后闪退
{
toposhape.Nullify();
return toposhape;
}
return toposhape;
}
void OCCCabin_Bool::Perform2(Space space) //20170601 by czb
{
OCCLib occLib;
clock_t start,finish; //typedef long clock_t;
double totaltime;
start=clock(); //clock():确定处理器当前时间
if(space.X1 > space.X2) //尾端面应小于首端面
{
return;
}
//船体
BRepBuilderAPI_Copy cp(this->solid);
TopoDS_Shape solid1 = cp.Shape();
//计算并设定船体坐标范围
Bnd_Box B;
BRepBndLib::Add(solid1,B);
Standard_Real axmin,aymin,azmin,axmax,aymax,azmax;
B.Get(axmin,aymin,azmin,axmax,aymax,azmax);
hullMinX = axmin - 0.001;
hullMaxX = axmax + 0.001;
hullMinY = aymin - 0.001;
hullMaxY = aymax + 0.001;
hullMinZ = azmin - 0.001;
hullMaxZ = azmax + 0.001;
//前后位置面特征点
vector<gp_Pnt2d> p2dSetFront = ConvertPoint2dSet2(space.FCharacterPoints, width, height);
vector<gp_Pnt2d> p2dSetBack = ConvertPoint2dSet2(space.LCharacterPoints, width, height);
if(p2dSetBack.size() == 0 || p2dSetFront.size() == 0)
{
return;
}
vector<gp_Pnt> pSetFront = CreatePointSet(p2dSetFront, max(space.X1,this->hullMinX)); //space.X1);
vector<gp_Pnt> pSetBack = CreatePointSet(p2dSetBack, min(space.X2,this->hullMaxX));//space.X2);
//参数体
TopoDS_Shell shell;
shell = CreateShell(pSetFront, pSetBack);
TopoDS_Solid solid2 = BRepBuilderAPI_MakeSolid(shell).Solid();
this->result = solid2;
return;
//this->result = TopoSolidBrepAlgo(2,solid1,solid2);
/*if(IsReversed(solid2))
{
solid2.Reverse();
}
if(IsReversed(solid1))
{
solid1.Reverse();
}*/
BRepAlgoAPI_Common com(solid2, solid1);
if(com.IsDone())
{
this->result = com.Shape();
}
else
{
TopoDS_Compound c;
BRep_Builder b;
b.MakeCompound(c);
b.Add(c,solid1);
b.Add(c,solid2);
this->result = c;
}
}
vector<gp_Pnt2d> OCCCabin_Bool::ConvertPoint2dSet(double* values, double width, double height)
{
vector<gp_Pnt2d> pSet, result;
double lw = -1 * width / 2;
double rw = width / 2;
double th = height / 2;
double bh = -1 * height / 2+10; //20161107 by yangchen
double len = (width + height) / 2;
int count = 0;
vector<int> indexs;
vector<int> boundIndex;
vector<TopoDS_Edge> edgeSet;
for(double* val = values; *val < 999.9; val++,count++)
{
double dy = (*val);
double dz = (*(++val));
int y = (int)dy;
int z = (int)dz;
bool isBound = false;
if(y == 777) // Y+见Statics.convertSpecToDigital
{
dy = rw;
isBound = true;
}
else if(y == -777) // Y-
{
dy = lw;
isBound = true;
}
if(z == 888) // Z+
{
dz = th;
isBound = true;
}
else if(z == -888) //Z-
{
dz = bh;
isBound = true;
}
if(abs(y) == 999) // P+ P-
{
indexs.push_back(count);
isBound = true;
}
pSet.push_back(gp_Pnt2d(dy, dz));
if(isBound)
{
boundIndex.push_back(count);
}
}
for(int i = 0; i < indexs.size(); i++)
{
int index = indexs[i];
gp_Pnt2d& p = pSet[index];
gp_Pnt2d temp;
if(p.X() > 0)
{
temp = pSet[(index + 1) % count];
}
else
{
temp = pSet[(index - 1+ count) % count];
}
double angle = (p.Y() / 360.0) * 2 * PI;
double y = cos(angle) * len + temp.X();
double z = sin(angle) * len + temp.Y();
if(y > rw)
{
y = rw;
z = tan(angle) * (y - temp.X()) + temp.Y();
if(z > th)
{
z = th;
y = 1 / tan(angle) * (z - temp.Y()) + temp.X();
}
else if(z < bh)
{
z = bh;
y = 1 / tan(angle) * (z - temp.Y()) + temp.X();
}
}
else if(y < lw)
{
y = lw;
z = tan(angle) * (y - temp.X()) + temp.Y();
if(z > th)
{
z = th;
y = 1 / tan(angle) * (z - temp.Y()) + temp.X();
}
else if(z < bh)
{
z = bh;
y = 1 / tan(angle) * (z - temp.Y()) + temp.X();
}
}
if(z > th)
{
z = th;
y = 1/ tan(angle) * (z - temp.Y()) + temp.X();
if(y > rw)
{
y = rw;
z = tan(angle) * (y - temp.X()) + temp.Y();
}
else if(y < lw)
{
y = lw;
z = tan(angle) * (y - temp.X()) + temp.Y();
}
}
else if(z < bh)
{
z = bh;
y = 1/ tan(angle) * (z - temp.Y()) + temp.X();
if(y > rw)
{
y = rw;
z = tan(angle) * (y - temp.X()) + temp.Y();
}
else if(y < lw)
{
y = lw;
z = tan(angle) * (y - temp.X()) + temp.Y();
}
}
p.SetX(y);
p.SetY(z);
}
//所有点必须在框内
for(int i = 0; i < pSet.size(); i++)
{
if(abs(pSet[i].X())>rw || abs(pSet[i].Y()) > th)
{
return result;
}
}
//调整顺序 保证特殊点在首尾
pSet = Reorder(pSet, boundIndex);
if(boundIndex.size() == 2)
{
boundIndex.clear();
boundIndex.push_back(0);
boundIndex.push_back(pSet.size() - 1);
}
//调整顺序
if(boundIndex.size() < 2 || pSet.size() == 2)
{
result = pSet;
return result;
}
//判断是否相交
TopoDS_Edge edge1, edge2;
int index,nextInd;
if(boundIndex[0] == 0 || (boundIndex[0] + pSet.size() - 1) % pSet.size() == boundIndex[1])
{
index = (boundIndex[0] + 1) % pSet.size();
}
else
{
index = (boundIndex[0] + pSet.size() - 1) % pSet.size();
}
edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0, pSet[boundIndex[0]].X(),pSet[boundIndex[0]].Y()),gp_Pnt(0,pSet[index].X(),pSet[index].Y()));
if(boundIndex[1] == 0 || (boundIndex[1] + pSet.size() - 1) % pSet.size() == boundIndex[0])
{
index = (boundIndex[1] + 1) % pSet.size();
}
else
{
index = (boundIndex[1] + pSet.size() - 1) % pSet.size();
}
edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(0, pSet[boundIndex[1]].X(),pSet[boundIndex[1]].Y()),gp_Pnt(0,pSet[index].X(),pSet[index].Y()));
BaseAlgo algo;
if(!algo.IsParallel(edge1, edge2) && pSet.size() > 3/*三个点时 会出现交点特征点的情况*/)
{
BRepExtrema_DistShapeShape dis(edge1, edge2);
dis.Perform();
if(dis.Value() < Precision::Confusion())
{
gp_Pnt p = dis.PointOnShape1(1);
gp_Pnt2d p2d(p.Y(), p.Z());
result.push_back(p2d);
for(int i = (boundIndex[0] + 1) % pSet.size(); i != boundIndex[1]; i = (i + 1) % pSet.size())
{
result.push_back(pSet[i]);
}
result.push_back(p2d);
return result;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
vector<gp_Pnt2d> boundPoints;
gp_Pnt2d p1 = pSet[boundIndex[0]];
gp_Pnt2d p2 = pSet[boundIndex[1]];
gp_Pnt2d pp1 = gp_Pnt2d(rw, th);
gp_Pnt2d pp2 = gp_Pnt2d(lw, th);
gp_Pnt2d pp3 = gp_Pnt2d(lw, bh);
gp_Pnt2d pp4 = gp_Pnt2d(rw, bh);
boundPoints.push_back(gp_Pnt2d(rw, th));
if(abs(p1.Y() - boundPoints.back().Y()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p1) > Precision::Confusion() && pp2.Distance(p1) > Precision::Confusion())
{
if(p1.X() < p.X())
{
boundPoints.push_back(p1);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p1);
boundPoints.push_back(p);
}
}
}
if(abs(p2.Y() - boundPoints.back().Y()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p2) > Precision::Confusion() && pp2.Distance(p2) > Precision::Confusion())
{
if(p2.X() < p.X())
{
boundPoints.push_back(p2);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p2);
boundPoints.push_back(p);
}
}
}
boundPoints.push_back(gp_Pnt2d(lw, th));
if(abs(p1.X() - boundPoints.back().X()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p1) > Precision::Confusion() && pp3.Distance(p1) > Precision::Confusion())
{
if(p1.Y() < p.Y())
{
boundPoints.push_back(p1);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p1);
boundPoints.push_back(p);
}
}
}
if(abs(p2.X() - boundPoints.back().X()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p2) > Precision::Confusion() && pp3.Distance(p2) > Precision::Confusion())
{
if(p2.Y() < p.Y())
{
boundPoints.push_back(p2);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p2);
boundPoints.push_back(p);
}
}
}
boundPoints.push_back(gp_Pnt2d(lw, bh));
if(abs(p1.Y() - boundPoints.back().Y()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p1) > Precision::Confusion() && pp4.Distance(p1) > Precision::Confusion())
{
if(p1.X() > p.X())
{
boundPoints.push_back(p1);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p1);
boundPoints.push_back(p);
}
}
}
if(abs(p2.Y() - boundPoints.back().Y()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p2) > Precision::Confusion() && pp4.Distance(p2) > Precision::Confusion())
{
if(p2.X() > p.X())
{
boundPoints.push_back(p2);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p2);
boundPoints.push_back(p);
}
}
}
boundPoints.push_back(gp_Pnt2d(rw, bh));
if(abs(p1.X() - boundPoints.back().X()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p1) > Precision::Confusion() && pp1.Distance(p1) > Precision::Confusion())
{
if(p1.Y() > p.Y())
{
boundPoints.push_back(p1);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p1);
boundPoints.push_back(p);
}
}
}
if(abs(p2.X() - boundPoints.back().X()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p2) > Precision::Confusion() && pp1.Distance(p2) > Precision::Confusion())
{
if(p2.Y() > p.Y())
{
boundPoints.push_back(p2);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p2);
boundPoints.push_back(p);
}
}
}
int index1,index2;
for(int i = 0; i < boundPoints.size(); i++)
{
if(boundPoints[i].Distance(p1) < Precision::Confusion())
{
index1 = i;
}
if(boundPoints[i].Distance(p2) < Precision::Confusion())
{
index2 = i;
}
}
//
for(int i = boundIndex[0]; i != boundIndex[1]; i = (i + 1) % pSet.size())
{
result.push_back(pSet[i]);
}
for(int i = index2; i != index1; i = (i + 1) % boundPoints.size())
{
result.push_back(boundPoints[i]);
}
result.push_back(p1);
//
return result;
}
vector<gp_Pnt2d> OCCCabin_Bool::ConvertPoint2dSet2(double* values, double width, double height) //20170601 by czb
{
vector<gp_Pnt2d> pSet, result;
double lw = this->hullMinY;
double rw = this->hullMaxY;
double th = this->hullMaxZ;
double bh = this->hullMinZ;
double len = (rw-lw + th-bh);
int count = 0;
vector<int> indexs;
vector<int> boundIndex;
vector<TopoDS_Edge> edgeSet;
for(double* val = values; *val < 999.9; val++,count++)
{
double dy = (*val);
double dz = (*(++val));
int y = (int)dy;
int z = (int)dz;
bool isBound = false;
if(y == 777) // Y+见Statics.convertSpecToDigital
{
dy = rw;
isBound = true;
}
else if(y == -777) // Y-
{
dy = lw;
isBound = true;
}
if(z == 888) // Z+
{
dz = th;
isBound = true;
}
else if(z == -888) //Z-
{
dz = bh;
isBound = true;
}
if(abs(y) == 999) // P+ P-
{
indexs.push_back(count);
isBound = true;
}
pSet.push_back(gp_Pnt2d(dy, dz));
if(isBound)
{
boundIndex.push_back(count);
}
}
//角度点处理 P
for(int i = 0; i < indexs.size(); i++)
{
int index = indexs[i];
gp_Pnt2d& p = pSet[index];
gp_Pnt2d temp;
if(p.X() > 0)
{
temp = pSet[(index + 1) % count];
}
else
{
temp = pSet[(index - 1+ count) % count];
}
double angle = (p.Y() / 360.0) * 2 * PI;
double y = cos(angle) * len + temp.X();
double z = sin(angle) * len + temp.Y();
if(y > rw)
{
y = rw;
z = tan(angle) * (y - temp.X()) + temp.Y();
if(z > th)
{
z = th;
y = 1 / tan(angle) * (z - temp.Y()) + temp.X();
}
else if(z < bh)
{
z = bh;
y = 1 / tan(angle) * (z - temp.Y()) + temp.X();
}
}
else if(y < lw)
{
y = lw;
z = tan(angle) * (y - temp.X()) + temp.Y();
if(z > th)
{
z = th;
y = 1 / tan(angle) * (z - temp.Y()) + temp.X();
}
else if(z < bh)
{
z = bh;
y = 1 / tan(angle) * (z - temp.Y()) + temp.X();
}
}
if(z > th)
{
z = th;
y = 1/ tan(angle) * (z - temp.Y()) + temp.X();
if(y > rw)
{
y = rw;
z = tan(angle) * (y - temp.X()) + temp.Y();
}
else if(y < lw)
{
y = lw;
z = tan(angle) * (y - temp.X()) + temp.Y();
}
}
else if(z < bh)
{
z = bh;
y = 1/ tan(angle) * (z - temp.Y()) + temp.X();
if(y > rw)
{
y = rw;
z = tan(angle) * (y - temp.X()) + temp.Y();
}
else if(y < lw)
{
y = lw;
z = tan(angle) * (y - temp.X()) + temp.Y();
}
}
p.SetX(y);
p.SetY(z);
}
return pSet;
/*
//所有点必须在框内
for(int i = 0; i < pSet.size(); i++)
{
if(abs(pSet[i].X())>rw || abs(pSet[i].Y()) > th)
{
return result;
}
}
//调整顺序 保证特殊点在首尾
pSet = Reorder(pSet, boundIndex);
if(boundIndex.size() == 2)
{
boundIndex.clear();
boundIndex.push_back(0);
boundIndex.push_back(pSet.size() - 1);
}
//调整顺序
if(boundIndex.size() < 2 || pSet.size() == 2)
{
result = pSet;
return result;
}
//判断是否相交
TopoDS_Edge edge1, edge2;
int index,nextInd;
if(boundIndex[0] == 0 || (boundIndex[0] + pSet.size() - 1) % pSet.size() == boundIndex[1])
{
index = (boundIndex[0] + 1) % pSet.size();
}
else
{
index = (boundIndex[0] + pSet.size() - 1) % pSet.size();
}
edge1 = BRepBuilderAPI_MakeEdge(gp_Pnt(0, pSet[boundIndex[0]].X(),pSet[boundIndex[0]].Y()),gp_Pnt(0,pSet[index].X(),pSet[index].Y()));
if(boundIndex[1] == 0 || (boundIndex[1] + pSet.size() - 1) % pSet.size() == boundIndex[0])
{
index = (boundIndex[1] + 1) % pSet.size();
}
else
{
index = (boundIndex[1] + pSet.size() - 1) % pSet.size();
}
edge2 = BRepBuilderAPI_MakeEdge(gp_Pnt(0, pSet[boundIndex[1]].X(),pSet[boundIndex[1]].Y()),gp_Pnt(0,pSet[index].X(),pSet[index].Y()));
BaseAlgo algo;
if(!algo.IsParallel(edge1, edge2) && pSet.size() > 3) //三个点时 会出现交点特征点的情况
{
BRepExtrema_DistShapeShape dis(edge1, edge2);
dis.Perform();
if(dis.Value() < Precision::Confusion())
{
gp_Pnt p = dis.PointOnShape1(1);
gp_Pnt2d p2d(p.Y(), p.Z());
result.push_back(p2d);
for(int i = (boundIndex[0] + 1) % pSet.size(); i != boundIndex[1]; i = (i + 1) % pSet.size())
{
result.push_back(pSet[i]);
}
result.push_back(p2d);
return result;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
vector<gp_Pnt2d> boundPoints;
gp_Pnt2d p1 = pSet[boundIndex[0]];
gp_Pnt2d p2 = pSet[boundIndex[1]];
gp_Pnt2d pp1 = gp_Pnt2d(rw, th);
gp_Pnt2d pp2 = gp_Pnt2d(lw, th);
gp_Pnt2d pp3 = gp_Pnt2d(lw, bh);
gp_Pnt2d pp4 = gp_Pnt2d(rw, bh);
boundPoints.push_back(gp_Pnt2d(rw, th));
if(abs(p1.Y() - boundPoints.back().Y()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p1) > Precision::Confusion() && pp2.Distance(p1) > Precision::Confusion())
{
if(p1.X() < p.X())
{
boundPoints.push_back(p1);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p1);
boundPoints.push_back(p);
}
}
}
if(abs(p2.Y() - boundPoints.back().Y()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p2) > Precision::Confusion() && pp2.Distance(p2) > Precision::Confusion())
{
if(p2.X() < p.X())
{
boundPoints.push_back(p2);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p2);
boundPoints.push_back(p);
}
}
}
boundPoints.push_back(gp_Pnt2d(lw, th));
if(abs(p1.X() - boundPoints.back().X()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p1) > Precision::Confusion() && pp3.Distance(p1) > Precision::Confusion())
{
if(p1.Y() < p.Y())
{
boundPoints.push_back(p1);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p1);
boundPoints.push_back(p);
}
}
}
if(abs(p2.X() - boundPoints.back().X()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p2) > Precision::Confusion() && pp3.Distance(p2) > Precision::Confusion())
{
if(p2.Y() < p.Y())
{
boundPoints.push_back(p2);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p2);
boundPoints.push_back(p);
}
}
}
boundPoints.push_back(gp_Pnt2d(lw, bh));
if(abs(p1.Y() - boundPoints.back().Y()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p1) > Precision::Confusion() && pp4.Distance(p1) > Precision::Confusion())
{
if(p1.X() > p.X())
{
boundPoints.push_back(p1);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p1);
boundPoints.push_back(p);
}
}
}
if(abs(p2.Y() - boundPoints.back().Y()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p2) > Precision::Confusion() && pp4.Distance(p2) > Precision::Confusion())
{
if(p2.X() > p.X())
{
boundPoints.push_back(p2);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p2);
boundPoints.push_back(p);
}
}
}
boundPoints.push_back(gp_Pnt2d(rw, bh));
if(abs(p1.X() - boundPoints.back().X()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p1) > Precision::Confusion() && pp1.Distance(p1) > Precision::Confusion())
{
if(p1.Y() > p.Y())
{
boundPoints.push_back(p1);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p1);
boundPoints.push_back(p);
}
}
}
if(abs(p2.X() - boundPoints.back().X()) < Precision::Confusion())
{
gp_Pnt2d p = boundPoints.back();
if(p.Distance(p2) > Precision::Confusion() && pp1.Distance(p2) > Precision::Confusion())
{
if(p2.Y() > p.Y())
{
boundPoints.push_back(p2);
}
else
{
boundPoints.pop_back();
boundPoints.push_back(p2);
boundPoints.push_back(p);
}
}
}
int index1,index2;
for(int i = 0; i < boundPoints.size(); i++)
{
if(boundPoints[i].Distance(p1) < Precision::Confusion())
{
index1 = i;
}
if(boundPoints[i].Distance(p2) < Precision::Confusion())
{
index2 = i;
}
}
//
for(int i = boundIndex[0]; i != boundIndex[1]; i = (i + 1) % pSet.size())
{
result.push_back(pSet[i]);
}
for(int i = index2; i != index1; i = (i + 1) % boundPoints.size())
{
result.push_back(boundPoints[i]);
}
result.push_back(p1);
//
return result;*/
}
TopoDS_Shell OCCCabin_Bool::CreateSplitShell(vector<gp_Pnt> pSet1, vector<gp_Pnt> pSet2)
{
TopoDS_Shell shell;
OCCLib occLib;
vector<TopoDS_Shape> shapeSet;
BRepOffsetAPI_Sewing sew;
if(pSet2.size() != pSet1.size() || pSet1.size() == 0)
{
return shell;
}
for(int i = 0; i < pSet1.size() - 1; i++)
{
int j = (i+1) % pSet1.size();
TopoDS_Face face = occLib.CreateFaceByPoints(pSet1[i], pSet1[j], pSet2[j], pSet2[i]);
shapeSet.push_back(face);
//sew.Add(face);
}
//sew.Perform();
//shell = TopoDS::Shell(sew.SewedShape());
shell = occLib.SewShell(shapeSet);
//throw shell;
return shell;
}
TopoDS_Shell OCCCabin_Bool::CreateShell(vector<gp_Pnt> pSet1, vector<gp_Pnt> pSet2)
{
TopoDS_Shell shell;
OCCLib occLib;
vector<TopoDS_Shape> shapeSet;
BRepOffsetAPI_Sewing sew;
if(pSet2.size() != pSet1.size() || pSet1.size() == 0)
{
return shell;
}
TopoDS_Face face;
face = occLib.CreatePlaneByPoints(pSet1,Standard_True);//首端面方向反向
shapeSet.push_back(face);
face = occLib.CreatePlaneByPoints(pSet2);
shapeSet.push_back(face);
for(int i = 0; i < pSet1.size() - 1; i++)
{
int j = (i+1) % pSet1.size();
face = occLib.CreateFaceByPoints(pSet1[i], pSet1[j], pSet2[j], pSet2[i]);
shapeSet.push_back(face);
//sew.Add(face);
}
//sew.Perform();
//shell = TopoDS::Shell(sew.SewedShape());
shell = occLib.SewShell(shapeSet);
//throw shell;
return shell;
}
vector<gp_Pnt> OCCCabin_Bool::CreatePointSet(vector<gp_Pnt2d> p2dSet, double d)
{
vector<gp_Pnt> pSet;
if(p2dSet.size() == 2)
{
//pSet.push_back(gp_Pnt(d, p2dSet[0].X(), p2dSet[0].Y()));
//pSet.push_back(gp_Pnt(d, p2dSet[0].X(), p2dSet[1].Y()));
//pSet.push_back(gp_Pnt(d, p2dSet[1].X(), p2dSet[1].Y()));
//pSet.push_back(gp_Pnt(d, p2dSet[1].X(), p2dSet[0].Y()));
//pSet.push_back(gp_Pnt(d, p2dSet[0].X(), p2dSet[0].Y()));
double xmin = p2dSet[0].X() > p2dSet[1].X() ? p2dSet[1].X() : p2dSet[0].X();
double xmax = p2dSet[0].X() > p2dSet[1].X() ? p2dSet[0].X() : p2dSet[1].X();
double ymin = p2dSet[0].Y() > p2dSet[1].Y() ? p2dSet[1].Y() : p2dSet[0].Y();
double ymax = p2dSet[0].Y() > p2dSet[1].Y() ? p2dSet[0].Y() : p2dSet[1].Y();
switch(dir)
{
case DIR_X:
pSet.push_back(gp_Pnt(d, xmax, ymax));
pSet.push_back(gp_Pnt(d, xmin, ymax));
pSet.push_back(gp_Pnt(d, xmin, ymin));
pSet.push_back(gp_Pnt(d, xmax, ymin));
pSet.push_back(gp_Pnt(d, xmax, ymax));
break;
case DIR_Y:
pSet.push_back(gp_Pnt(xmax, d, ymax));
pSet.push_back(gp_Pnt(xmin, d, ymax));
pSet.push_back(gp_Pnt(xmin, d, ymin));
pSet.push_back(gp_Pnt(xmax, d, ymin));
pSet.push_back(gp_Pnt(xmax, d, ymax));
break;
case DIR_Z:
pSet.push_back(gp_Pnt(xmax, ymax, d));
pSet.push_back(gp_Pnt(xmin, ymax, d));
pSet.push_back(gp_Pnt(xmin, ymin, d));
pSet.push_back(gp_Pnt(xmax, ymin, d));
pSet.push_back(gp_Pnt(xmax, ymax, d));
break;
}
}
else
{
for(int i = 0; i < p2dSet.size(); i++)
{
switch(dir)
{
case DIR_X:
pSet.push_back(gp_Pnt(d, p2dSet[i].X(), p2dSet[i].Y()));
break;
case DIR_Y:
pSet.push_back(gp_Pnt(p2dSet[i].X(), d, p2dSet[i].Y()));
break;
case DIR_Z:
pSet.push_back(gp_Pnt(p2dSet[i].X(), p2dSet[i].Y(), d));
break;
}
}
}
return pSet;
}
TopoDS_Face OCCCabin_Bool::CutEndFace(TopoDS_Face face, TopoDS_Shape shell, vector<gp_Pnt> pSet, bool isLeft)
{
TopoDS_Face TopoShape;
std::vector<TopoDS_Edge> faceBorder; // 面的边界
for(TopExp_Explorer ex_face(face, TopAbs_EDGE);ex_face.More();ex_face.Next())
{
TopoDS_Edge edge = TopoDS::Edge(ex_face.Current());
gp_Pnt p1,p2;
GetEdgeStartEndPoint(edge,p1,p2);
if(p1.Distance(p2) < Precision::Confusion())
{
continue;
}
faceBorder.push_back(edge);
}
BRepAlgoAPI_Section asect(face,shell,Standard_False);
asect.ComputePCurveOn1(Standard_True);
asect.Approximation(Standard_True);
asect.Build();
if(!asect.IsDone())
{
throw face;
}
TopoDS_Shape splitResult = asect.Shape();
BRepFeat_SplitShape asplit(face);
int count = 0;
for (TopExp_Explorer Ex(splitResult,TopAbs_EDGE); Ex.More(); Ex.Next())
{
TopoDS_Edge anEdge =TopoDS::Edge(Ex.Current());
gp_Pnt p1,p2;
GetEdgeStartEndPoint(anEdge, p1,p2);
bool isCoincide = false;
for(int i = 0; i < faceBorder.size(); i++)
{
if(CheckTwoEdgeOverlapByLinePointProject(anEdge,faceBorder[i]))
{
isCoincide = true;
break;
}
}
if(isCoincide)
{
continue;
}
//bool isReverse = true;
//for(int j = 0; j < pSet.size(); j++)
//{
// if(pSet[j].Distance(p1) < Precision::Confusion())
// {
// if(pSet[( j + 1) % pSet.size()].Distance(p2) < Precision::Confusion())
// {
// isReverse = false;
// break;
// }
// }
//}
//BaseAlgo algo;
//algo.PutPCurve(anEdge, face);
//if(isReverse ^ isLeft)
//{
// anEdge.Reverse();
//}
BaseAlgo algo;
algo.PutPCurve(anEdge, face);
if(!isLeft)
{
anEdge.Orientation(TopAbs_REVERSED);
}
else
{
anEdge.Orientation(TopAbs_FORWARD);
}
asplit.Add(anEdge, face);
count++;
}
if(count == 0)
{
return face;
}
TopTools_ListIteratorOfListOfShape theList;
try
{
asplit.Build();
}
catch (Standard_Failure e)
{
throw face;
}
theList = asplit.Left();
for (;theList.More();theList.Next())
{
TopoShape = TopoDS::Face(theList.Value());
}
return TopoShape;
}
TopoDS_Shape OCCCabin_Bool::GetResult()
{
return this->result;
}
vector<gp_Pnt2d> OCCCabin_Bool::Reorder( vector<gp_Pnt2d> pSet, vector<int> index )
{
if(index.size() == 0 )
{
return pSet;
}
if(index.size() == 1) //不保存这种情况
{
return pSet;
}
if(index.size() > 2) //不保存这种情况
{
return pSet;
}
int index1 = index[0];
int index2 = index[1];
if(index1 == 0 && index2 == pSet.size() - 1)
{
return pSet;
}
if(index2 != (index1+1)%pSet.size()) //不相邻 不保存这种情况
{
return pSet;
}
vector<gp_Pnt2d> result;
for(int i = 0; i < pSet.size(); i++)
{
result.push_back(pSet[(i + index2)%pSet.size()]);
}
return result;
}