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

2357 lines
56 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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