天天看點

【第三回】使用OCCT做類似AutoCAD的拉伸功能(Extrude)

        這幾周真心把我給累到了,突如其來一下子要接收消化那麼多新的知識,工作上面要用到的還有我自己感興趣研究的,基本上周末都沒得休息

【第三回】使用OCCT做類似AutoCAD的拉伸功能(Extrude)

。不過努力就有收獲,這幾周沒白忙活,工作上面對OCCT的使用已經摸出了點門道。

        AutoCAD中的拉伸功能有這幾個限制:待拉伸的模型不可以是自相交的(self-intersecting),拉伸出來的模型也不可是自相交的。AutoCAD在基于這兩個限制上可對線段,多段線以及面進行拉伸。拉伸可以沿方向(Direction),路徑(Path)和錐角(Taper Angle)進行。而在OCCT中它并沒有針對拉伸等這些業務層級别的功能進行封裝實作,要實作沿方向,路徑和錐角進行拉伸,需要用到BRepPrimAPI_MakePrism(沿方向拉伸),BRepOffsetAPI_MakePipe(沿路徑拉伸)和BRepOffsetAPI_DraftAngle(根據錐角使模型産生形變)。由于OCCT所有實作的功能都是功能級别上的,這幾個類所實作的拉伸的效果是沒有AutoCAD中的這幾個限制的。下面貼出這幾個類的使用示例:

BRepPrimAPI_MakePrism(沿方向拉伸):

TopoDS_Shape makeExtrude(const TopoDS_Shape& oriShape, const gp_Vec& dir)
{
	TopoDS_Shape rstShape;
	try
	{
		TopoDS_Shape oriShape1 = oriShape;
		if (oriShape1.ShapeType() == TopAbs_WIRE)
			oriShape1 = BRepBuilderAPI_MakeFace(TopoDS::Wire(oriShape1));

		rstShape = BRepPrimAPI_MakePrism(oriShape1, dir);
	}
	catch (const Standard_Failure& err)
	{
		std::cout<<"\nStandard_Failure: "<<err.GetMessageString();
	}
	catch (...)
	{
		std::cout<<"\nBRepPrimAPI_MakePrism some unknown errors occur";
	}

	return rstShape;
}
           

BRepOffsetAPI_MakePipe(沿路徑拉伸):

TopoDS_Shape makeExtrude(const TopoDS_Shape& oriShape)
{
	Handle(Geom_TrimmedCurve) arc = GC_MakeArcOfCircle(gp_Pnt(0, 0, 0), gp_Pnt(10, 10, 0), gp_Pnt(0, 20, 0));
	Handle(Geom_TrimmedCurve) arc2 = GC_MakeArcOfCircle(gp_Pnt(0, 20, 0), gp_Pnt(-10, 30, 0), gp_Pnt(0, 40, 0));
	Handle(Geom_TrimmedCurve) seg = GC_MakeSegment(gp_Pnt(0, 40, 0), gp_Pnt(20, 40, 0));
	Handle(Geom_TrimmedCurve) seg1 = GC_MakeSegment(gp_Pnt(20, 40, 0), gp_Pnt(20, 60, 0));
	TopoDS_Edge arcEdge = BRepBuilderAPI_MakeEdge(arc);
	TopoDS_Edge arcEdge1 = BRepBuilderAPI_MakeEdge(arc2);
	TopoDS_Edge segEdge = BRepBuilderAPI_MakeEdge(seg);
	TopoDS_Edge segEdge1 = BRepBuilderAPI_MakeEdge(seg1);
	TopoDS_Wire arcWire = BRepBuilderAPI_MakeWire(arcEdge, arcEdge1, segEdge/*, segEdge1*/); //return arcWire;

	TopoDS_Shape rstShape;
	try
	{
		rstShape = BRepOffsetAPI_MakePipe(arcWire, oriShape);
	}
	catch (const Standard_Failure& err)
	{
		std::cout<<"\nStandard_Failure: "<<err.GetMessageString();
	}
	catch (...)
	{
		std::cout<<"\nBRepOffsetAPI_MakePipe some unknown error occur";
	}

	return rstShape;
}
           

其中這兩個類的拉伸規則如下:

【第三回】使用OCCT做類似AutoCAD的拉伸功能(Extrude)

還有一個類BRepOffsetAPI_MakePipeShell隻能對線框以下的模型進行拉伸,即它最高隻能拉伸出shell,而它相對于BRepOffsetAPI_MakePipe有一個較靈活的地方是:它提供了幾個方法:

BRepOffsetAPI_MakePipeShell::Add

BRepOffsetAPI_MakePipeShell::SetMode

void BRepOffsetAPI_MakePipeShell::Add	(	const TopoDS_Shape & 	Profile,
const Standard_Boolean 	WithContact = Standard_False,
const Standard_Boolean 	WithCorrection = Standard_False 
)	
           
void BRepOffsetAPI_MakePipeShell::SetMode  ( const gp_Dir &  BiNormal ) 
           

第一個方法裡面有一個參數WithCorrection,當為true時,那麼它在做拉伸時,拉伸的面的法向會校正為拉伸路徑曲線的切線方向,當為false時,拉伸的面的法向會保持原有的法向不變;第二個方法是設定拉伸面的固定法向,也就是說在拉伸的過程中拉伸面的法向始終保持BiNormal不變。這兩個方法不能同時使用!

而BRepOffsetAPI_MakePipe在拉伸的過程是是保持原有的拉伸面的法向不變,這個特征滿足AutoCAD中拉伸功能的特征!

還有一個BRepOffsetAPI_DraftAngle(根據錐角使模型産生形變)的示例:

TopoDS_Shape S = BRepPrimAPI_MakeBox(200.,300.,150.);
	BRepOffsetAPI_DraftAngle adraft(S);
	TopExp_Explorer Ex;
	for (Ex.Init(S,TopAbs_FACE); Ex.More(); Ex.Next()) {
		TopoDS_Face F = TopoDS::Face(Ex.Current());
		Handle(Geom_Plane) surf = Handle(Geom_Plane)::DownCast(BRep_Tool::Surface(F));
		gp_Pln apln = surf->Pln();
		gp_Dir dirF = apln.Axis().Direction();
		if (dirF.IsNormal(gp_Dir(0.,0.,1.),Precision::Angular()))
			adraft.Add(F, gp_Dir(0.,0.,1.), 15.*M_PI/180, gp_Pln(gp::XOY()));
	}
	TopoDS_Shape resultShape = adraft.Shape();
           

       我接下來還要做的一件事就是将它們進行封裝,封裝成業務層的拉伸功能,下周又是攻堅的一站

【第三回】使用OCCT做類似AutoCAD的拉伸功能(Extrude)

,不過這周是真的得好好休息了。。

       在執行拉伸功能的時候檢測待拉伸的模型是否合法,拉伸後的模型是否合法可使用BRepAlgoAPI_Check,這個類可以檢測自幹涉(self-interference),也就是自相交(self-intersection)檢測。

       有了這些類,那麼封裝拉伸功能基本上可以完成的了!

繼續閱讀