Netgen是一款优秀的开源四面体网格划分程序,如果是准备做CAE方向,网格是其中的一个重点,本文就Netgen6.2集成做个简要流程,流程也是比较简单,具体如下:
第一.编译netgen with OCC,这个网上资料很多,因为我们是准备集成netgen的库(nglib),所以我在cmake时候,在UESER选项中只勾选了USE_OCC,截图如下:
基本的cmake配置是:camke3.12版本,VS2015 release 64,选择OCC的时候我直接把OCC7.4的cmake对应就行了。截图如下:
编译还需要对应VS版本的ZLIB,这个可以网上找或者自己编译,难度不大。之后的编译就不复述了,比较简单。
第二.关于如何使用nglib,首先可以在nglib文件夹内可以看到自带的例子:ng_occ.cpp ng_stl.cpp,ng_vol.cpp等等,是对应不同文件类型的实例,值得参考。
有一点值得注意的是,自带的接口是以文件作为参数的,而且本人测试过,对于STP文件,如果模型是组合体,那么划分网格就会失败,常常来说,网格的对象的是一个Topds_shape,因此需要自己加个接口,将Topds_shape直接传入Ng_OCC_Geometry,具体可以参考读取stp文件时的函数内部代码,比较简单。
第三。关于如何在OSG中显示,由于可以获取网格的顶点左边以及组成网格的单元,所以用OSG显示相对比较简单,具体看我的参考代码:
netgen网格划分写入OSG并显示/
//生成netgen网格并显示
bool QFormDoc::GeneratNGmesh()
{
TopoDS_Shape ashape = GetmodeShape();
using namespace nglib;
cout << "Netgen NgLib - OpenCascade Test Case" << endl;
// Define pointer to OCC Geometry
Ng_OCC_Geometry *occ_geom;
Ng_Mesh *occ_mesh;
Ng_Meshing_Parameters mp;
TopTools_IndexedMapOfShape FMap;
Ng_OCC_TopTools_IndexedMapOfShape *occ_fmap = (Ng_OCC_TopTools_IndexedMapOfShape*)&FMap;
// Result of Netgen Operations
Ng_Result ng_res;
// Initialise the Netgen Core library
Ng_Init();
occ_geom = Ng_OCC_Load_Shape(ashape);
if (!occ_geom)
{
//cout << "Error reading in STEP File: " << filename << endl;
system("pause");
return FALSE;
}
//cout << "Successfully loaded STEP File: " << filename << endl;
occ_mesh = Ng_NewMesh();
ng_res = Ng_OCC_GetFMap(occ_geom, occ_fmap);
cout << "ng_res = " << ng_res << endl;
if (!FMap.Extent())
{
cout << "Error retrieving Face map...." << endl;
system("pause");
return FALSE;
}
//cout << "Successfully extracted the Face Map....:" << FMap.Extent() << endl;
mp.uselocalh = 1;
mp.elementsperedge = 2.0;
mp.elementspercurve = 2.0;
mp.maxh = 1000.0;
mp.grading = 0.5;
mp.closeedgeenable = 0;
mp.closeedgefact = 1.0;
mp.optsurfmeshenable = 0;
mp.optvolmeshenable = 0;
cout << "Setting Local Mesh size....." << endl;
cout << "OCC Mesh Pointer before call = " << occ_mesh << endl;
Ng_OCC_SetLocalMeshSize(occ_geom, occ_mesh, &mp);
cout << "Local Mesh size successfully set....." << endl;
cout << "OCC Mesh Pointer after call = " << occ_mesh << endl;
cout << "Creating Edge Mesh....." << endl;
ng_res = Ng_OCC_GenerateEdgeMesh(occ_geom, occ_mesh, &mp);
if (ng_res != NG_OK)
{
Ng_DeleteMesh(occ_mesh);
cout << "Error creating Edge Mesh.... Aborting!!" << endl;
system("pause");
return FALSE;
}
else
{
cout << "Edge Mesh successfully created....." << endl;
cout << "Number of points = " << Ng_GetNP(occ_mesh) << endl;
}
cout << "Creating Surface Mesh....." << endl;
ng_res = Ng_OCC_GenerateSurfaceMesh(occ_geom, occ_mesh, &mp);
if (ng_res != NG_OK)
{
Ng_DeleteMesh(occ_mesh);
cout << "Error creating Surface Mesh..... Aborting!!" << endl;
system("pause");
return FALSE;
}
else
{
cout << "Surface Mesh successfully created....." << endl;
cout << "Number of points = " << Ng_GetNP(occ_mesh) << endl;
cout << "Number of surface elements = " << Ng_GetNSE(occ_mesh) << endl;
}
//细化网格
Ng_OCC_Uniform_Refinement(occ_geom, occ_mesh);
//获取面网格数据
int np = 0;
np = nglib::Ng_GetNP(occ_mesh);
/*for (int i = 1; i <= np; ++i)
{
nglib::Ng_GetPoint(occ_mesh, i, point);
std::cout << i << ": " << point[0] << ", " << point[1] << ", " << point[2] << std::endl;
}*/
int ne = 0;
ne = nglib::Ng_GetNSE(occ_mesh);
/*int p[3] = { 0.0 };
for (int i = 0; i < ne; i++)
{
nglib::Ng_GetSurfaceElement(occ_mesh, i, p);
std::cout << i << ": " << p[0] << ", " << p[1] << ", " << p[2] << std::endl;
}*/
//显示面网格
osg::ref_ptr
osg::ref_ptr
osg::ref_ptr
osg::ref_ptr
osg::Vec4Array* colors = new osg::Vec4Array;
int p[3] = { 0.0 };
double point1[3] = { 0.0 };
double point2[3] = { 0.0 };
double point3[3] = { 0.0 };
for (int i = 1; i <= ne; i++)
{
nglib::Ng_GetSurfaceElement(occ_mesh, i, p);
nglib::Ng_GetPoint(occ_mesh, p[0], point1);
nglib::Ng_GetPoint(occ_mesh, p[1], point2);
nglib::Ng_GetPoint(occ_mesh, p[2], point3);
//把点转换成OSG的点
gp_Pnt node1(point1[0], point1[1], point1[2]);
gp_Pnt node2(point2[0], point2[1], point2[2]);
gp_Pnt node3(point3[0], point3[1], point3[2]);
//
gp_XYZ vector12(node2.XYZ() - node1.XYZ());
gp_XYZ vector13(node3.XYZ() - node1.XYZ());
gp_XYZ normal = vector12.Crossed(vector13);
Standard_Real rModulus = normal.Modulus();
if (rModulus > gp::Resolution())
{
normal.Normalize();
}
else
{
normal.SetCoord(0., 0., 0.);
}
vertices->push_back(osg::Vec3(node1.X(), node1.Y(), node1.Z()));
vertices->push_back(osg::Vec3(node2.X(), node2.Y(), node2.Z()));
vertices->push_back(osg::Vec3(node3.X(), node3.Y(), node3.Z()));
normals->push_back(osg::Vec3(normal.X(), normal.Y(), normal.Z()));
colors->push_back(osg::Vec4(0.0, 1.0, 0.0, 1.0));
colors->push_back(osg::Vec4(0.0, 1.0, 0.0, 1.0));
colors->push_back(osg::Vec4(0.0, 1.0, 0.0, 1.0));
}
triGeom->setColorArray(colors, osg::Array::BIND_OVERALL);
triGeom->setVertexArray(vertices.get());
triGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, vertices->size()));
triGeom->setNormalArray(normals);
triGeom->setNormalBinding(osg::Geometry::BIND_OVERALL);
triGeom->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
triGeom->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);
//triGeom->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK), osg::StateAttribute::ON | osg::StateAttribute::PROTECTED);
geode->addDrawable(triGeom);
m_osgViewer->getSceneData()->asGroup()->getChild(1)->setNodeMask(0);
m_osgViewer->getRoot()->addChild(geode);
osg::StateSet* stateset = node->getOrCreateStateSet();
osg::ref_ptr
polygonMode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
stateset->setAttribute(polygonMode.get(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
//
cout << "Creating Volume Mesh....." << endl;
ng_res = Ng_GenerateVolumeMesh(occ_mesh, &mp);
cout << "Volume Mesh successfully created....." << endl;
cout << "Number of points = " << Ng_GetNP(occ_mesh) << endl;
cout << "Number of volume elements = " << Ng_GetNE(occ_mesh) << endl;
return true;
}
//
下方截图是划分的效果:
上图是读取stp模型后的效果,接下来看下网格划分效果:
网格划分已经能成功在OSG中显示了,目前存在的困惑是在划分体网格时候,耗时比较长。不知道是不是有方案可以解决? 如有任何问题,请您加我QQ:1623451686。恳请指正和交流。