OpenCASCADE Make Face With Holes
eryar@163.com
OpenCASCADE提供了構(gòu)造Face的類BRepBuilderAPI_MakeFace,使用這個類可以構(gòu)造出帶孔的面。如下圖所示:

當(dāng)然,要得到上圖所示的結(jié)果,還可以使用Boolean操作,用一個面去Cut幾個圓柱。當(dāng)使用布爾操作就會涉及到一些復(fù)雜算法,如求交,重構(gòu)Topo體等,比較耗時。既然可以直接在生成面的時候挖孔,這個不涉及復(fù)雜算法,速度、穩(wěn)定性都比使用布爾操作要好。本文主要來介紹如何使用BRepBuilderAPI_MakeFace來生成帶孔的面,及其注意事項。直接上代碼:
#include <gp_Circ.hxx>
#include <gp_Pln.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepTools.hxx>
#pragma comment(lib, "TKernel.lib")
#pragma comment(lib, "TKMath.lib")
#pragma comment(lib, "TKG2d.lib")
#pragma comment(lib, "TKG3d.lib")
#pragma comment(lib, "TKGeomBase.lib")
#pragma comment(lib, "TKGeomAlgo.lib")
#pragma comment(lib, "TKBRep.lib")
#pragma comment(lib, "TKTopAlgo.lib")
void makeFaceTest()
{
gp_Pln aPlane;
gp_Circ aCircle1(gp::XOY(), 1.0);
gp_Circ aCircle2(gp::XOY(), 1.0);
gp_Circ aCircle3(gp::XOY(), 1.0);
aCircle1.SetLocation(gp_Pnt(3.0, 3.0, 0.0));
aCircle2.SetLocation(gp_Pnt(7.0, 3.0, 0.0));
aCircle3.SetLocation(gp_Pnt(3.0, 7.0, 0.0));
BRepBuilderAPI_MakeEdge anEdgeMaker1(aCircle1);
BRepBuilderAPI_MakeEdge anEdgeMaker2(aCircle2);
BRepBuilderAPI_MakeEdge anEdgeMaker3(aCircle3);
BRepBuilderAPI_MakeWire aWireMaker1(anEdgeMaker1.Edge());
BRepBuilderAPI_MakeWire aWireMaker2(anEdgeMaker2.Edge());
BRepBuilderAPI_MakeWire aWireMaker3(anEdgeMaker3.Edge());
BRepBuilderAPI_MakeFace aFaceMaker(aPlane, 0.0, 10.0, 0.0, 10.0);
if (aWireMaker1.IsDone())
{
aFaceMaker.Add(aWireMaker1.Wire());
}
if (aWireMaker2.IsDone())
{
aFaceMaker.Add(aWireMaker2.Wire());
}
if (aWireMaker3.IsDone())
{
aFaceMaker.Add(aWireMaker3.Wire());
}
if (aFaceMaker.IsDone())
{
BRepTools::Write(aFaceMaker.Shape(), "d:/face.brep");
}
}
int main(int argc, char* argv[])
{
makeFaceTest();
return 0;
}
上面代碼就是在一個平面上開三個孔,最后在D盤生成face.brep文件。在Draw Test Harness中加載并顯示這個文件得到:

當(dāng)切換到線框顯示模式時,和預(yù)期效果一致。但是當(dāng)切換到著色顯示模式時,發(fā)現(xiàn)生成的面和預(yù)期的效果剛好相反。這是什么原因呢?
在Draw Test Harness中輸入命令pcruve來檢查,如下圖所示:

根據(jù)pcurve命令的提示得知,藍色的方向應(yīng)該反向,紅色的為外環(huán)。所以得知,內(nèi)環(huán)孔的方向反了。修改代碼,直接將Wire的方向Reverse。修改后的代碼如下:
#include <gp_Circ.hxx>
#include <gp_Pln.hxx>
#include <TopoDS_Wire.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepTools.hxx>
#pragma comment(lib, "TKernel.lib")
#pragma comment(lib, "TKMath.lib")
#pragma comment(lib, "TKG2d.lib")
#pragma comment(lib, "TKG3d.lib")
#pragma comment(lib, "TKGeomBase.lib")
#pragma comment(lib, "TKGeomAlgo.lib")
#pragma comment(lib, "TKBRep.lib")
#pragma comment(lib, "TKTopAlgo.lib")
void makeFaceTest()
{
gp_Pln aPlane;
gp_Circ aCircle1(gp::XOY(), 1.0);
gp_Circ aCircle2(gp::XOY(), 1.0);
gp_Circ aCircle3(gp::XOY(), 1.0);
aCircle1.SetLocation(gp_Pnt(3.0, 3.0, 0.0));
aCircle2.SetLocation(gp_Pnt(7.0, 3.0, 0.0));
aCircle3.SetLocation(gp_Pnt(3.0, 7.0, 0.0));
BRepBuilderAPI_MakeEdge anEdgeMaker1(aCircle1);
BRepBuilderAPI_MakeEdge anEdgeMaker2(aCircle2);
BRepBuilderAPI_MakeEdge anEdgeMaker3(aCircle3);
BRepBuilderAPI_MakeWire aWireMaker1(anEdgeMaker1.Edge());
BRepBuilderAPI_MakeWire aWireMaker2(anEdgeMaker2.Edge());
BRepBuilderAPI_MakeWire aWireMaker3(anEdgeMaker3.Edge());
BRepBuilderAPI_MakeFace aFaceMaker(aPlane, 0.0, 10.0, 0.0, 10.0);
if (aWireMaker1.IsDone())
{
TopoDS_Wire aWire1 = aWireMaker1.Wire();
aWire1.Reverse();
aFaceMaker.Add(aWire1);
}
if (aWireMaker2.IsDone())
{
TopoDS_Wire aWire2 = aWireMaker2.Wire();
aWire2.Reverse();
aFaceMaker.Add(aWire2);
}
if (aWireMaker3.IsDone())
{
TopoDS_Wire aWire3 = aWireMaker3.Wire();
aWire3.Reverse();
aFaceMaker.Add(aWire3);
}
if (aFaceMaker.IsDone())
{
BRepTools::Write(aFaceMaker.Shape(), "d:/face.brep");
}
}
int main(int argc, char* argv[])
{
makeFaceTest();
return 0;
}
重新加載新生成的face.brep并使用pcurve查看,得到如下圖所示的效果:

從上圖可知,這時得到的為預(yù)期的效果。綜上所述,如果要直接使用BRepBuilderAPI_MakeFace來生成帶有孔的面,需要自己為外環(huán)和內(nèi)環(huán)的方向負責(zé),opencascade對此不作檢查。當(dāng)面顯示不正確時,可以使用Draw Test Harness的pcurve命令來檢查。一個帶孔的面的pcurve的規(guī)則為:外環(huán)為逆時針方向;內(nèi)環(huán)孔的方向為順時針方向。
基于直接生成的帶孔的面,還可以進一步使用放樣算法來造型,如拉伸,旋轉(zhuǎn)等,如下圖所示。這樣就可以避免使用布爾操作,提高造型算法的性能和穩(wěn)定性。
