# OpenCascade Shape Representation in OpenSceneGraph

eryar@163.com

## 一、引言 Introduction

“实体造型技术主流的是边界表达BRep，就是模型由面和边组成，这些面和边都是参数化的解析曲面和曲线，当拉伸或切割实体操作时候，就是用生成的实体和已有的实体进行实体布尔运算，其实是进行的面和边的相交运算，从而算出到新的面或者边。比如圆柱面和平面相交，以前的圆柱面分成了两个，同时产生出一条相交的空间椭圆曲线段，这些解析面/线边要通过三角化算法离散成三角网格或者线段条作为逼近表达，才能用OpenGL画出来。”以上内容来自博客：http://yrcpp.blog.163.com/blog/static/126045259201310199515969/ ，感谢网友的分享，言简意赅地把造型的核心进行了说明。

## 二、程序示例

```/*
*
*           File : Main.cpp
*         Author : eryar@163.com
*           Date : 2013-12-03 18:09
*        Version : 1.0v
*
*    Description : Draw OpenCascade polygon Curves of the edge
*                  and triangulations of the face in OpenSceneGraph.
*                  When you want to display the shape in the computer,
*                  you can not display the geometry exactly, the only
*                  way to show them is in the approximation form.
*
*      Key Words : OpenCascade, polygon curve, triangulation,
*                  discrete edge, discrete face, OpenSceneGraph, OSG
*
*/

#define WNT
#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>

#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\")

// OpenSceneGraph library.
#include <osgViewer/Viewer>
#include <osgGA/StateSetManipulator>
#include <osgViewer/ViewerEventHandlers>

#pragma comment(lib, \"osgd.lib\")
#pragma comment(lib, \"osgDBd.lib\")
#pragma comment(lib, \"osgViewerd.lib\")

/*
* @breif Descret the shape: edge.
*        For Edge will be discreted to polylines; (GCPnts_TangentialDeflection)
*        To get the polyline of the edge, use BRep_Tool::Polygon3D(Edge, L);
*/
osg::Node* BuildPolyline(const TopoDS_Edge& edge, double deflection = 0.1)
{
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
osg::ref_ptr<osg::Geometry> linesGeom = new osg::Geometry();
osg::ref_ptr<osg::Vec3Array> pointsVec = new osg::Vec3Array();

TopLoc_Location location;

BRepMesh::Mesh(edge, deflection);
Handle_Poly_Polygon3D polyline = BRep_Tool::Polygon3D(edge, location);

for (int i = 1; i < polyline->NbNodes(); i++)
{
gp_Pnt point = polyline->Nodes().Value(i);

pointsVec->push_back(osg::Vec3(point.X(), point.Y(), point.Z()));
}

// Set the color of the polyline.
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0f, 1.0f, 0.0f, 0.0f));
linesGeom->setColorArray(colors.get());
linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL);

// Set vertex array.
linesGeom->setVertexArray(pointsVec);

return geode.release();
}

/*
* @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);
*/
osg::Node* BuildMesh(const TopoDS_Face& face, double deflection = 0.1)
{
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
osg::ref_ptr<osg::Geometry> triGeom = new osg::Geometry();
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array();
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array();

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();

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());

gp_XYZ vector12(vertex2.XYZ() - vertex1.XYZ());
gp_XYZ vector13(vertex3.XYZ() - vertex1.XYZ());
gp_XYZ normal = vector12.Crossed(vector13);
Standard_Real rModulus = normal.Modulus();

if (rModulus > gp::Resolution())
{
normal.Normalize();
}
else
{
normal.SetCoord(0., 0., 0.);
}

//if (face.Orientable() != TopAbs_FORWARD)
//{
//    normal.Reverse();
//}

vertices->push_back(osg::Vec3(vertex1.X(), vertex1.Y(), vertex1.Z()));
vertices->push_back(osg::Vec3(vertex2.X(), vertex2.Y(), vertex2.Z()));
vertices->push_back(osg::Vec3(vertex3.X(), vertex3.Y(), vertex3.Z()));

normals->push_back(osg::Vec3(normal.X(), normal.Y(), normal.Z()));
}

triGeom->setVertexArray(vertices.get());

triGeom->setNormalArray(normals);
triGeom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);

return geode.release();
}

osg::Node* BuildScene(void)
{
osg::ref_ptr<osg::Group> root = new osg::Group();

gp_Ax2 axis;

// 1. Test circle while deflection is default 0.1;
TopoDS_Edge circleEdge1 = BRepBuilderAPI_MakeEdge(gp_Circ(axis, 6.0));

// 2. Test circle while deflection is 0.001.
axis.SetLocation(gp_Pnt(8.0, 0.0, 0.0));
axis.SetDirection(gp_Dir(1.0, 1.0, 1.0));

TopoDS_Edge circleEdge2 = BRepBuilderAPI_MakeEdge(gp_Circ(axis, 6.0));

// 3. Test ellipse while deflection is 1.0.
TopoDS_Edge ellipseEdge = BRepBuilderAPI_MakeEdge(gp_Elips(gp::XOY(), 16.0, 8.0));

// 4. 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));

// 5. 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));

// 6. 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));

return root.release();
}

int main(void)
{
osgViewer::Viewer myViewer;

myViewer.setSceneData(BuildScene());

return myViewer.run();
}```

Figure 2.1 Edge and Face representation in OpenSceneGraph

Figure 2.2 Edge and Face representation in OpenSceneGraph