摘要Abstract:本文通過程序實例,將OpenCascade中的拓樸數據(邊、面)離散化後在OpenSceneGraph中進行顯示。有了這些離散數據,就可以不用OpenCascade的顯示模塊了,可以使用其他顯示引擎對形狀進行顯示。即若要線框模式顯示形狀時,就繪製離散形狀拓樸邊後得到的多段線;若要實體渲染模式顯示形狀時,就繪製離散形狀拓樸面得到的三角網格。理解這些概念也有助於理解顯示模塊的實現,及拓樸數據中包含的幾何數據的意義。
一、引言 Introduction
Opencascade中的模型是Brep結構,可以通過三角化後,利用VTK的渲染引擎進行顯示,從而能夠利用幾何內核和網格處理算法的共同優點。
以前看《計算機圖形學》相關的書時,從數學概念到具體實現的橋樑總是無法銜接。現在,通過學習OpenCascade,終於把這些都串起來了。正如上面網友所說,面和邊要在OpenGL中顯示出來就需要離散化,即把邊離散爲多段線,把面離散爲三角網格。這樣就可以把用參數精確表示的幾何數據在計算機佈滿像素點的屏幕上逼近顯示了。
本文通過程序實例,將OpenCascade中的拓樸數據(邊、面)離散化後在VTK中進行顯示。有了這些離散數據,就可以不用OpenCascade的顯示模塊了,可以使用其他顯示引擎對形狀進行顯示。即若要線框模式顯示形狀時,就繪製離散形狀拓樸邊後得到的多段線;若要實體渲染模式顯示形狀時,就繪製離散形狀拓樸面得到的三角網格。理解這些概念也有助於理解顯示模塊的實現,及拓樸數據中包含的幾何數據的意義。
二、程序示例
以下通過一個具體程序實例,來對OpenCascade中的拓樸邊和拓樸面進行離散化。
// sampleExample.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
// OpenCascade library.
#include <gp_Circ.hxx>
#include <gp_Elips.hxx>
#include <gp_Sphere.hxx>
#include <Poly_Polygon3D.hxx>
#include <Poly_Triangulation.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <BRep_Tool.hxx>
#include <BRepMesh.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
//vtk lib
#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 <vtkTriangle.h>
#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")
/*
* @breif Descret the shape: face.
* For Face will be discreted to triangles; (BRepMesh_FastDiscret)
* To get the triangles of the face, use BRep_Tool::Triangulation(Face, L);
*/
void BuildMesh(vtkRenderer* render, const TopoDS_Face& face, double deflection = 0.1)
{
TopLoc_Location location;
BRepMesh::Mesh(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> cells = vtkSmartPointer<vtkCellArray>::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<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
cells->InsertNextCell(triangle);
id++;
}
polyData->SetPoints(points);
polyData->SetPolys(cells);
vtkSmartPointer<vtkPolyDataMapper> sourceMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
sourceMapper->SetInput(polyData);
vtkSmartPointer<vtkActor> sourceActor = vtkSmartPointer<vtkActor>::New();
sourceActor->SetMapper(sourceMapper);
sourceActor->GetProperty()->SetColor(1,0,0);
render->AddActor(sourceActor);
}
/* build the scene to visualization */
void BuildScene(vtkRenderer* render)
{
gp_Ax2 axis;
// 1. Test sphere face while deflection is default 0.1.
axis.SetLocation(gp_Pnt(26.0, 0.0, 0.0));
TopoDS_Face sphereFace1 = BRepBuilderAPI_MakeFace(gp_Sphere(axis, 8.0));
BuildMesh(render, sphereFace1);
// 2. Test sphere face while deflection is 2.0.
axis.SetLocation(gp_Pnt(26.0, 18.0, 0.0));
TopoDS_Face sphereFace2 = BRepBuilderAPI_MakeFace(gp_Sphere(axis, 8.0));
BuildMesh(render,sphereFace2, 2.0);
// 3. Test sphere face while deflection is 0.001.
axis.SetLocation(gp_Pnt(26.0, -18.0, 0.0));
TopoDS_Face sphereFace3 = BRepBuilderAPI_MakeFace(gp_Sphere(axis, 8.0));
BuildMesh(render, sphereFace3, 0.001);
}
int _tmain(int argc, _TCHAR* argv[])
{
// Create a renderer, render window, and interactor
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
//build mesh
BuildScene(renderer);
renderer->SetBackground(1,1,1);
// Render and interact
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}