OCCT 建模,VTK显示

2019/6/21

在OCCT中visualization中有现成的VTK接口 从Topo::DS_Shape到Mapper的接口如下所示:

IVtkOCC_Shape::Handle aShapeImpl = new IVtkOCC_Shape(MakeBottle(20,30,8));
	
	vtkSmartPointer<IVtkTools_ShapeDataSource> DS = vtkSmartPointer<IVtkTools_ShapeDataSource>::New();
	DS->SetShape(aShapeImpl);
	
	vtkSmartPointer<vtkPolyDataMapper> Mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	Mapper->SetInputConnection(DS->GetOutputPort());

画图的例子采用的是OCCT官方教程中的二锅头的例子 图形的类型为Topo::DS_Shape

另外还有一个球的生成作为测试 图形的类型为Topo::DS_Face

#include <vtkAutoInit.h> //avoid error:0xC0000005
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkInteractionStyle);

//Libs from OCCT
#pragma comment(lib, "TKernel.lib")
#pragma comment(lib, "TKMath.lib")
#pragma comment(lib, "TKBRep.lib")
#pragma comment(lib, "TKMesh.lib")
#pragma comment(lib, "TKTopAlgo.lib")

#include <TCollection_AsciiString.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Face.hxx>
#include <gp_Circ.hxx>
#include <gp_Elips.hxx>
#include <gp_Sphere.hxx>
#include <gp_Pnt.hxx>
#include <Geom_Line.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Plane.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom2d_Ellipse.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <GC_MakeArcOfCircle.hxx>
#include <GC_MakeSegment.hxx>
#include <Poly_Polygon3D.hxx>
#include <Poly_Triangulation.hxx>
#include <BRep_Builder.hxx>
#include <BRepBuilderAPI.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepprimAPI_MakeCylinder.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRep_Tool.hxx>
#include <BRepMesh.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepFilletAPI_MakeFillet.hxx>
#include <BRepOffsetAPI_MakeThickSolid.hxx>
#include <BRepLib.hxx>
#include <TopExp_Explorer.hxx>
#include <GCE2d_MakeSegment.hxx>
#include <BRepOffsetAPI_ThruSections.hxx>
#include <IVtkOCC_Shape.hxx>
#include <IVtkTools_ShapeDataSource.hxx>

//Libs from VTK
#include <vtkSmartPointer.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkCellArray.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkLine.h>
#include <vtkTriangle.h>
#include <vtkPolyDataWriter.h>
#include <vtkVertexGlyphFilter.h>

//OCC shape
//standard 基本类型
TopoDS_Shape MakeBottle(const Standard_Real myWidth, const Standard_Real myHeight,
	const Standard_Real myThickness)
{
	// Profile : Define Support Points
    //gp:几何元素
	gp_Pnt aPnt1(-myWidth / 2., 0, 0);
	gp_Pnt aPnt2(-myWidth / 2., -myThickness / 4., 0);
	gp_Pnt aPnt3(0, -myThickness / 2., 0);
	gp_Pnt aPnt4(myWidth / 2., -myThickness / 4., 0);
	gp_Pnt aPnt5(myWidth / 2., 0, 0);
	// Profile : Define the Geometry
    //geom构建几何类型 Handle为智能指针
	Handle(Geom_TrimmedCurve) anArcOfCircle = GC_MakeArcOfCircle(aPnt2, aPnt3, aPnt4);
	Handle(Geom_TrimmedCurve) aSegment1 = GC_MakeSegment(aPnt1, aPnt2);
	Handle(Geom_TrimmedCurve) aSegment2 = GC_MakeSegment(aPnt4, aPnt5);
	// Profile : Define the Topology
    //topods几何拓扑结构 包含几何信息 方向 位置
    //brepbuilderapi 使用几何类型构造几何拓扑结构
	TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aSegment1);
	TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(anArcOfCircle);
	TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge(aSegment2);
	TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3);
	// Complete Profile
	gp_Ax1 xAxis = gp::OX();
	gp_Trsf aTrsf;
	aTrsf.SetMirror(xAxis);
	BRepBuilderAPI_Transform aBRepTrsf(aWire, aTrsf);
	TopoDS_Shape aMirroredShape = aBRepTrsf.Shape();
	TopoDS_Wire aMirroredWire = TopoDS::Wire(aMirroredShape);
	BRepBuilderAPI_MakeWire mkWire;
	mkWire.Add(aWire);
	mkWire.Add(aMirroredWire);
	TopoDS_Wire myWireProfile = mkWire.Wire();
	// Body : Prism the Profile
    // brepprimapi扫描构建几何体
	TopoDS_Face myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile);
	gp_Vec aPrismVec(0, 0, myHeight);
	TopoDS_Shape myBody = BRepPrimAPI_MakePrism(myFaceProfile, aPrismVec);
	// Body : Apply Fillets
    //brepfilletapi倒角 圆角等
    //topexp——explorer用于遍历元素 for循环
	BRepFilletAPI_MakeFillet mkFillet(myBody);
	TopExp_Explorer anEdgeExplorer(myBody, TopAbs_EDGE);
	while (anEdgeExplorer.More()){
		TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExplorer.Current());
		//Add edge to fillet algorithm
		mkFillet.Add(myThickness / 12., anEdge);
		anEdgeExplorer.Next();
	}
	myBody = mkFillet.Shape();
	// Body : Add the Neck
    //brepalgo 算法包 布尔运算 裁剪等
	gp_Pnt neckLocation(0, 0, myHeight);
	gp_Dir neckAxis = gp::DZ();
	gp_Ax2 neckAx2(neckLocation, neckAxis);
	Standard_Real myNeckRadius = myThickness / 4.;
	Standard_Real myNeckHeight = myHeight / 10.;
	BRepPrimAPI_MakeCylinder MKCylinder(neckAx2, myNeckRadius, myNeckHeight);
	TopoDS_Shape myNeck = MKCylinder.Shape();
	myBody = BRepAlgoAPI_Fuse(myBody, myNeck);
	// Body : Create a Hollowed Solid
	TopoDS_Face   faceToRemove;
	Standard_Real zMax = -1;
	for (TopExp_Explorer aFaceExplorer(myBody, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next()){
		TopoDS_Face aFace = TopoDS::Face(aFaceExplorer.Current());
		// Check if <aFace> is the top face of the bottle's neck 
		Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);
		if (aSurface->DynamicType() == STANDARD_TYPE(Geom_Plane)){
			Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface);
			gp_Pnt aPnt = aPlane->Location();
			Standard_Real aZ = aPnt.Z();
			if (aZ > zMax){
				zMax = aZ;
				faceToRemove = aFace;
			}
		}
	}
    //toptools 数据结构类型 表 树等
	TopTools_ListOfShape facesToRemove;
	facesToRemove.Append(faceToRemove);
    //brepoffsetapi 通过偏移来生成实体
	BRepOffsetAPI_MakeThickSolid BodyMaker;
	BodyMaker.MakeThickSolidByJoin(myBody, facesToRemove, -myThickness / 50, 1.e-3);
	myBody = BodyMaker.Shape();
	// Threading : Create Surfaces
	Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99);
	Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05);
	// Threading : Define 2D Curves
	gp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.);
	gp_Dir2d aDir(2. * M_PI, myNeckHeight / 4.);
	gp_Ax2d anAx2d(aPnt, aDir);
	Standard_Real aMajor = 2. * M_PI;
	Standard_Real aMinor = myNeckHeight / 10;
	Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);
	Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4);
	Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI);
	Handle(Geom2d_TrimmedCurve) anArc2 = new Geom2d_TrimmedCurve(anEllipse2, 0, M_PI);
	gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0);
	gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI);
	Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2);
	// Threading : Build Edges and Wires
	TopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1);
	TopoDS_Edge anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment, aCyl1);
	TopoDS_Edge anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2);
	TopoDS_Edge anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment, aCyl2);
	TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1);
	TopoDS_Wire threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2, anEdge2OnSurf2);
	BRepLib::BuildCurves3d(threadingWire1);
	BRepLib::BuildCurves3d(threadingWire2);
	// Create Threading 
	BRepOffsetAPI_ThruSections aTool(Standard_True);
	aTool.AddWire(threadingWire1);
	aTool.AddWire(threadingWire2);
	aTool.CheckCompatibility(Standard_False);
	TopoDS_Shape myThreading = aTool.Shape();
	// Building the Resulting Compound 
	TopoDS_Compound aRes;
	BRep_Builder aBuilder;
	aBuilder.MakeCompound(aRes);
	aBuilder.Add(aRes, myBody);
	aBuilder.Add(aRes, myThreading);
	return aRes;
}

//Mesh&Data transmission
void BuildMesh(vtkRenderer* render, const TopoDS_Face& face, double deflection = 0.1)
{
	TopLoc_Location location;
	BRepMesh_IncrementalMesh(face, deflection);
        Handle_Poly_Triangulation triFace = BRep_Tool::Triangulation(face, location);

	Standard_Integer nTriangles = triFace->NbTriangles();

	gp_Pnt vertex1;
	gp_Pnt vertex2;
	gp_Pnt vertex3;

	Standard_Integer nVertexIndex1 = 0;
	Standard_Integer nVertexIndex2 = 0;
	Standard_Integer nVertexIndex3 = 0;

	TColgp_Array1OfPnt nodes(1, triFace->NbNodes());
	Poly_Array1OfTriangle triangles(1, triFace->NbTriangles());

	nodes = triFace->Nodes();
	triangles = triFace->Triangles();

	vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
	vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
	vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
	vtkSmartPointer<vtkPolyData> pointData = vtkSmartPointer<vtkPolyData>::New();
	vtkSmartPointer<vtkPolyData> lineData = vtkSmartPointer<vtkPolyData>::New();
	vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();

	points->Allocate(nTriangles * 3);
	cells->Allocate(nTriangles);

	int id = 0;

	for (Standard_Integer i = 1; i <= nTriangles; i++)
	{
		Poly_Triangle aTriangle = triangles.Value(i);

		aTriangle.Get(nVertexIndex1, nVertexIndex2, nVertexIndex3);

		vertex1 = nodes.Value(nVertexIndex1).Transformed(location.Transformation());
		vertex2 = nodes.Value(nVertexIndex2).Transformed(location.Transformation());
		vertex3 = nodes.Value(nVertexIndex3).Transformed(location.Transformation());

		points->InsertNextPoint(vertex1.X(), vertex1.Y(), vertex1.Z());
		points->InsertNextPoint(vertex2.X(), vertex2.Y(), vertex2.Z());
		points->InsertNextPoint(vertex3.X(), vertex3.Y(), vertex3.Z());
		
		vtkSmartPointer<vtkLine> line0 = vtkSmartPointer<vtkLine>::New();
		line0->GetPointIds()->SetId(0, id * 3);
		line0->GetPointIds()->SetId(1, id * 3 + 1);
		vtkSmartPointer<vtkLine> line1 = vtkSmartPointer<vtkLine>::New();
		line1->GetPointIds()->SetId(0, id * 3 + 1);
		line1->GetPointIds()->SetId(1, id * 3 + 2);
		vtkSmartPointer<vtkLine> line2 = vtkSmartPointer<vtkLine>::New();
		line2->GetPointIds()->SetId(0, id * 3 + 2);
		line2->GetPointIds()->SetId(1, id * 3);
		
		vtkSmartPointer<vtkTriangle> triangle = vtkSmartPointer<vtkTriangle>::New();
		triangle->GetPointIds()->SetId(0, id * 3);
		triangle->GetPointIds()->SetId(1, id * 3 + 1);
		triangle->GetPointIds()->SetId(2, id * 3 + 2);

		// Add the triangle to a cell array
		lines->InsertNextCell(line0);
		lines->InsertNextCell(line1);
		lines->InsertNextCell(line2);
		cells->InsertNextCell(triangle);
		id++;
	}
	pointData->SetPoints(points);
	vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter =vtkSmartPointer<vtkVertexGlyphFilter>::New();
	glyphFilter->SetInputData(pointData);
	glyphFilter->Update();
	lineData->SetPoints(points);
	lineData->SetLines(lines);
	polyData->SetPoints(points);
	polyData->SetPolys(cells);

	/*
	vtkSmartPointer<vtkPolyDataWriter> writer = vtkSmartPointer<vtkPolyDataWriter>::New();
	writer->SetFileName("Mesh.vtk");
	writer->SetInputData(polyData);
	writer->Write();
	*/

	vtkSmartPointer<vtkPolyDataMapper> pointMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	pointMapper->SetInputData(glyphFilter->GetOutput());

	vtkSmartPointer<vtkPolyDataMapper> lineMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	pointMapper->SetInputData(lineData);

	vtkSmartPointer<vtkPolyDataMapper> faceMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	faceMapper->SetInputData(polyData);

	vtkSmartPointer<vtkActor> pointActor = vtkSmartPointer<vtkActor>::New();
	pointActor->SetMapper(pointMapper);
	pointActor->GetProperty()->SetPointSize(3);
	pointActor->GetProperty()->SetColor(1, 1, 1);
	pointActor->GetProperty()->SetOpacity(1); 
	vtkSmartPointer<vtkActor> lineActor = vtkSmartPointer<vtkActor>::New();
	lineActor->SetMapper(lineMapper);
	lineActor->GetProperty()->SetLineWidth(3);
	lineActor->GetProperty()->SetColor(1, 0, 0);
	vtkSmartPointer<vtkActor> faceActor = vtkSmartPointer<vtkActor>::New();
	faceActor->SetMapper(faceMapper);
	faceActor->GetProperty()->SetColor(1, 0, 0);
	
	render->AddActor(pointActor);
	render->AddActor(lineActor);
	render->AddActor(faceActor);
}

void TestScene(vtkRenderer* render)
{
	gp_Ax2 axis;
	axis.SetAxis(gp::OX());
	axis.SetLocation(gp_Pnt(0.0, 0.0, 0.0));
	TopoDS_Face sphereFace1 = BRepBuilderAPI_MakeFace(gp_Sphere(axis, 8.0));
	BuildMesh(render, sphereFace1);
}

void BuildScene(vtkRenderer* render, TopoDS_Shape model,double deflection)
{
	for (TopExp_Explorer aFaceExplorer(model, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next()){
		TopoDS_Face aFace = TopoDS::Face(aFaceExplorer.Current());
		BuildMesh(render, aFace,deflection);
	}
}

int main(int argc, char* argv[])
{
	// Create a renderer, render window, and interactor
	vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
	vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->SetSize(1200, 900);
	renderWindow->AddRenderer(renderer);

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	//build mesh
	BuildScene(renderer, MakeBottle(20,30,8),0.01);
    TestScene(renderer);

	renderer->SetBackground(0, 0.2, 0.8);

	// Render and interact
	renderWindow->Render();
	renderWindowInteractor->Start();

	return 0;
}

显示效果图:

VTK的管线配置还是比较简单的 建立相应的数据结构 将对应的数据传过去就行

比较麻烦的地方:

1.类型 TopoDS_Shape和TopoDS_Face的问题 即类型层次和转换的问题

2.三角剖分相关的源码

源码中间三角剖分最终都成为了Topo::DS_TFace中间的Trianglation 之后就没有办法看了

一层一层嵌套很难受

参考资料之后 觉得还是要从BRep_FastDiscretFace.cxx里面看

3.如何生成体网格

目前仅能实现一条参数轴(U)的离散

即仅能通过暴力方法 生成旋转和拉伸生成实体的面网格

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值