【OCCT+ImGUI系列】010-BRepMesh-网格化IncrementalMesh

在这里插入图片描述

在三维模型处理中,网格化(Meshing)是将几何模型离散为三角面片的关键步骤。本文基于 OpenCascade 的 BRepMesh_IncrementalMesh 类,结合交互式演示系统,详解网格化参数调节、实时更新与可视化。


一、BRepMesh_IncrementalMesh 核心机制

BRepMesh_IncrementalMesh 是 OpenCascade 的增量式网格生成器,采用动态精度控制算法,支持以下关键参数:

  • LinearDeflection:线性偏差(模型空间单位)
  • AngularDeflection:角度偏差(弧度制)
  • InParallel:启用多线程加速

通过构造球体示例演示核心调用方式:

TopoDS_Shape shape = BRepPrimAPI_MakeSphere(50.0).Shape();
IMeshTools_Parameters params;
params.Deflection = 1.0;
params.Angle = 30 * M_PI / 180;

BRepMesh_IncrementalMesh mesher;
mesher.SetShape(shape);
mesher.ChangeParameters() = params;
mesher.Perform(); // 执行网格化

二、交互式教学系统功能

1. 动态参数调节与实时更新

在这里插入图片描述
在这里插入图片描述

通过 ImGui 滑动条实现参数动态调节,修改后触发网格重建:

// 线性偏差调节(0.1~0.7)
if (ImGui::SliderFloat("Linear Deflection", &linearDeflection, 0.1f, 0.7f)) {
    bMeshDirty = true; // 设置网格更新标志
}

// 角度偏差调节(5°~30°)
float angularDeg = angularDeflection * 180 / M_PI;
if (ImGui::SliderFloat("Angular Deflection", &angularDeg, 5.0f, 30.0f)) {
    angularDeflection = angularDeg * M_PI / 180;
    bMeshDirty = true;
}

参数修改后通过bMeshDirty标志触发updateMesh函数,保证视图实时响应

2. 网格清除与重置

通过BRepTools::Clean清除模型三角化数据,配合上下文更新实现网格重置:

void clearTriangulation(const TopoDS_Shape& shape) {
    for (TopExp_Explorer exp(shape, TopAbs_FACE); exp.More(); exp.Next()) {
        BRepTools::Clean(TopoDS::Face(exp.Current()));
    }
}
3. 三角化信息统计

遍历所有面的三角化数据,统计总三角形数量:

int totalTriangles = 0;
for (TopExp_Explorer exp(shape, TopAbs_FACE); exp.More(); exp.Next()) {
    Handle(Poly_Triangulation) tri = ...;
    if (!tri.IsNull()) totalTriangles += tri->NbTriangles();
}
ImGui::Text("Total Triangles: %d", totalTriangles);
4. 网格线框可视化

提取每个三角面片的边线,生成红色线框辅助显示:

void drawTriangulations(...) {
    for (each triangle in triangulation) {
        gp_Pnt p1 = tri->Node(n1).Transformed(...);
        // 创建三角形边线
        BRepBuilderAPI_MakePolygon poly;
        poly.Add(p1); poly.Add(p2); poly.Add(p3); poly.Close();
        
        Handle(AIS_Shape) aisTri = new AIS_Shape(poly.Shape());
        aisTri->SetColor(Quantity_NOC_RED);
        context->Display(aisTri, false);
    }
}

三、高级技巧与注意事项

  1. 多线程加速
    启用InParallel参数可提升复杂模型处理速度:

    meshParams.InParallel = true; // 开启并行计算
    
  2. 网格生成验证
    检查IsDone()状态确保网格生成成功:

    if (!mesher.IsDone()) {
        std::cerr << "Mesh generation failed!" << std::endl;
    }
    
  3. 显示模式控制
    强制设置AIS_Shape显示模式,增强可视化效果:

    aisShape->SetDisplayMode(AIS_Shaded); // 实体着色模式
    aisShape->Attributes()->SetFaceBoundaryDraw(true); // 显示面边界
    

四、代码

#pragma once

#include "pch.h"
#include <format>
#include <string>
#include <mutex>
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepPrimAPI_MakeSphere.hxx> // 新增头文件
#include <BRepLib_ToolTriangulatedShape.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <TopExp_Explorer.hxx>
#include <Poly_Triangulation.hxx>
#include <AIS_Shape.hxx>
#include <TopoDS.hxx>
#include "BaseScene.h"
#include "VisSceneComponents.h"
#include "TutorialWindow.h"
#include "CodeHintAction.h"

class BRepMesh010 : public BaseScene, public VisSceneComponents, public TutorialWindow {
public:
    BRepMesh010() {
        openTutorialWindow();
    }
     
    void displayScene(const Handle(V3d_View)& view, const Handle(AIS_InteractiveContext)& context) override {
        if (!bIsSceneInit) {
            sceneInit(view, context);
            bIsSceneInit = true;
        }

        if (bMeshDirty) {
            updateMesh(context);
            bMeshDirty = false; 
        }

        renderTutorialWindow(context);
    }

    void customInitTutorialWindow(const Handle(AIS_InteractiveContext)&) override {}

private:
    Handle(AIS_Shape)       aisShape;
    CodeHintManager         hintMgr;  
    TopoDS_Shape            meshShape;
    IMeshTools_Parameters   meshParams;
    std::mutex              meshMutex;

    float linearDeflection = 1.0f;
    float angularDeflectionDeg = 30.0f;
    float minSize = 0.0f;
    bool isProcessing = false;       // 标记是否正在处理


    bool bMeshDirty = false; // 参数变化刷新标志位

    void sceneInit(const Handle(V3d_View)&, const Handle(AIS_InteractiveContext)& context) override {
        meshShape =  BRepPrimAPI_MakeSphere(50.0).Shape();
        updateMesh(context);
    }

    void updateMesh(const Handle(AIS_InteractiveContext)& context) {

        std::lock_guard<std::mutex> lock(meshMutex); // 自动加锁

        // 开始处理
        isProcessing = true;
        clearTriangulation(meshShape);

        meshParams.Deflection = linearDeflection;
        meshParams.Angle = angularDeflectionDeg * M_PI / 180.0;
        meshParams.InParallel = true;

        BRepMesh_IncrementalMesh mesher;
        mesher.SetShape(meshShape);
        mesher.ChangeParameters() = meshParams;
        mesher.Perform();

        hintMgr.AddHint("Mesh", "mesher.Perform();");

        // 添加网格生成验证
        if (!mesher.IsDone()) {
            std::cerr << "Mesh generation failed!" << std::endl;
            return;
        }

        aisShape = new AIS_Shape(meshShape);
        // 强制设置显示模式为网格
        //aisShape->SetDisplayMode(AIS_Shaded);  // 或 AIS_WireFrame
        aisShape->Attributes()->SetFaceBoundaryDraw(true);
        context->RemoveAll(true);
        context->Display(aisShape, true);
        context->UpdateCurrentViewer();  // 强制刷新视图

        drawTriangulations(meshShape, context);
    }

    void clearTriangulation(const TopoDS_Shape& shape) {
        for (TopExp_Explorer exp(shape, TopAbs_FACE); exp.More(); exp.Next()) {
            TopoDS_Face face = TopoDS::Face(exp.Current());
            BRepTools::Clean(face); // 移除 Poly_Triangulation
        }
    }

    void renderTutorialContent(const Handle(AIS_InteractiveContext)& context) override {
        ImGui::Text("BRepMesh_IncrementalMesh 教学示例");
        ImGui::Separator();


        float oldLinearDeflection = linearDeflection;
        if (ImGui::SliderFloat("Linear Deflection", &linearDeflection, 0.1f, 0.7f, "%.2f")) {
            if (oldLinearDeflection != linearDeflection) {
                bMeshDirty = true;
            }
        }

        float oldAngularDeflectionDeg = angularDeflectionDeg;
        if (ImGui::SliderFloat("Angular Deflection (deg)", &angularDeflectionDeg, 5.0f, 11.0f, "%.1f")) {
            if (oldAngularDeflectionDeg != angularDeflectionDeg) {
                bMeshDirty = true;
            }
        }

        if (ImGui::Button("Clear Triangulation")) {
            BRepTools::Clean(meshShape);
            context->RemoveAll(true);
            hintMgr.AddHint("BRepTools::Clean", "BRepTools::Clean(meshShape);");
        }

        if (ImGui::Button("Reset Default")) {
            linearDeflection = 1.0f;
            angularDeflectionDeg = 30.0f;
            minSize = 0.0f;
            updateMesh(context);
        }

        if (aisShape) {
            ImGui::Separator();
            ImGui::Text("Triangulation Info:");

            int totalTriangles = 0;
            for (TopExp_Explorer exp(meshShape, TopAbs_FACE); exp.More(); exp.Next()) {
                TopLoc_Location loc;
                Handle(Poly_Triangulation) tri = BRep_Tool::Triangulation(TopoDS::Face(exp.Current()), loc);
                if (!tri.IsNull()) {
                    totalTriangles += tri->NbTriangles();
                }
            }
            ImGui::Text("Total Triangles: %d", totalTriangles);
        }

		// 渲染提示窗口
        hintMgr.RenderWindow();
    }

    void drawTriangulations(const TopoDS_Shape& shape, const Handle(AIS_InteractiveContext)& context) {
        for (TopExp_Explorer faceExp(shape, TopAbs_FACE); faceExp.More(); faceExp.Next()) {
            TopoDS_Face face = TopoDS::Face(faceExp.Current());
            TopLoc_Location loc;
            Handle(Poly_Triangulation) tri = BRep_Tool::Triangulation(face, loc);

            if (tri.IsNull()) continue;

            const Poly_Array1OfTriangle& triangles = tri->Triangles();

            for (int i = triangles.Lower(); i <= triangles.Upper(); ++i) {
                int n1, n2, n3;
                triangles(i).Get(n1, n2, n3);

                // 使用 tri->Node(index) 获取三角形顶点坐标
                gp_Pnt p1 = tri->Node(n1).Transformed(loc.Transformation());
                gp_Pnt p2 = tri->Node(n2).Transformed(loc.Transformation());
                gp_Pnt p3 = tri->Node(n3).Transformed(loc.Transformation());

                // 创建一个三角形边线展示
                BRepBuilderAPI_MakePolygon triPoly;
                triPoly.Add(p1);
                triPoly.Add(p2);
                triPoly.Add(p3);
                triPoly.Add(p1);
                triPoly.Close();

                Handle(AIS_Shape) aisTri = new AIS_Shape(triPoly.Shape());
                aisTri->SetDisplayMode(AIS_WireFrame);
                aisTri->SetColor(Quantity_NOC_RED);
                context->Display(aisTri, false);
            }
        }

        context->UpdateCurrentViewer();
    }

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值