初探OSG+OpenCascade(简称:OCC)在QT上的实践之尝试集成Netgen6.2网格划分程序

Netgen是一款优秀的开源四面体网格划分程序,如果是准备做CAE方向,网格是其中的一个重点,本文就Netgen6.2集成做个简要流程,流程也是比较简单,具体如下:

第一.编译netgen with OCC,这个网上资料很多,因为我们是准备集成netgen的库(nglib),所以我在cmake时候,在UESER选项中只勾选了USE_OCC,截图如下:

初探OSG+OpenCascade(简称:OCC)在QT上的实践之尝试集成Netgen6.2网格划分程序_第1张图片

基本的cmake配置是:camke3.12版本,VS2015 release 64,选择OCC的时候我直接把OCC7.4的cmake对应就行了。截图如下:

初探OSG+OpenCascade(简称:OCC)在QT上的实践之尝试集成Netgen6.2网格划分程序_第2张图片

编译还需要对应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 geode = new osg::Geode();
    osg::ref_ptr triGeom = new osg::Geometry();
    osg::ref_ptr vertices = new osg::Vec3Array();
    osg::ref_ptr normals = new osg::Vec3Array();
    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 = new osg::PolygonMode();
    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;
}

//

下方截图是划分的效果:

初探OSG+OpenCascade(简称:OCC)在QT上的实践之尝试集成Netgen6.2网格划分程序_第3张图片

上图是读取stp模型后的效果,接下来看下网格划分效果:

初探OSG+OpenCascade(简称:OCC)在QT上的实践之尝试集成Netgen6.2网格划分程序_第4张图片

 

初探OSG+OpenCascade(简称:OCC)在QT上的实践之尝试集成Netgen6.2网格划分程序_第5张图片

 

初探OSG+OpenCascade(简称:OCC)在QT上的实践之尝试集成Netgen6.2网格划分程序_第6张图片

网格划分已经能成功在OSG中显示了,目前存在的困惑是在划分体网格时候,耗时比较长。不知道是不是有方案可以解决? 如有任何问题,请您加我QQ:1623451686。恳请指正和交流。

你可能感兴趣的:(OSG,OpenCascade,negtgen,gmesh,qt,osg,mesh)