第20章 后处理插件(Plugin):视图数据运算与变换
20.1 学习目标
- 理解 Gmsh 插件系统(Plugin)的定位:对后处理视图(View)数据进行运算、变换与可视化增强的模块化工具集
- 掌握
plugin::setNumber()/plugin::setString()设置插件参数、plugin::run()执行插件并生成新视图的标准工作流 - 熟练使用六种常用内置插件:等值面(Isosurface)、切平面(CutPlane)、二维截面映射(CutMap)、表面提取(Skin)、流线图(StreamLines)与探针采样(Probe)
- 理解插件运行结果自动产生新 View 的机制,以及多插件串联构建后处理流水线的思路
- 了解插件在 CAE 中的典型应用场景:截面应力云图、流场流线可视化、参数化分析中的标量场批量提取
20.2 核心概念说明
20.2.1 插件(Plugin)是什么
在 Gmsh 的架构中,前处理(几何建模 + 网格划分)由 model 命名空间负责,而后处理(Post-Processing)则由 View(视图) 和 Plugin(插件) 两部分协作完成。
View(视图):后处理数据的容器,包含标量场(Scalar Field)、矢量场(Vector Field)或张量场(Tensor Field),可以是基于列表的(list-based,独立于网格)或基于模型的(model-based,绑定到特定网格)。
Plugin(插件):对 View 中的数据进行运算或变换的模块。一个插件读取一个或多个源 View,执行特定算法,输出一个新的 View。例如: - 从三维标量场中提取等值面 - 在指定平面上截取截面云图 - 从矢量场中追踪流线
插件的运行流程可以概括为:
源 View (Source) ──→ [Plugin: setNumber/setString 配置参数] ──→ plugin::run() ──→ 新 View (Result)
20.2.2 常用内置插件速览
Gmsh 静态链接了数十个内置插件,以下是 CAE 后处理中最常用的六个:
| 插件名 | 功能 | 适用场景 | 输入要求 | 输出 |
|---|---|---|---|---|
| Isosurface | 从3D标量场提取等值面 | 应力/温度等值面可视化 | 3D 标量 View | 2D 曲面 View |
| CutPlane | 用平面截取3D视图 | 任意角度截面云图 | 3D View(标量/矢量) | 2D 截面 View |
| CutMap | 将3D标量场在截平面上的值展平为2D彩色图 | 截面应力分布精确判读 | 3D 标量 View | 2D 彩色图 View |
| Skin | 提取3D视图的外表面 | 仅关心表面场分布时 | 3D View | 2D 表面 View |
| StreamLines | 从矢量场追踪流线/迹线 | 流场、磁场、热通量方向 | 3D 矢量 View | 1D 线 View |
| Probe | 在指定坐标点采样场值 | 参数化分析、监控点提取 | 任意 View | 终端输出 + 可选 View |
此外还有 ModifyComponents(修改/交换矢量或张量分量)、Annotate(添加文字标注)、Smooth(场值平滑)、Transform(视图几何变换)等辅助插件。
20.2.3 插件参数系统
所有插件都通过统一的参数接口进行配置:
gmsh::plugin::setNumber("PluginName", "ParameterName", value); // 数值参数
gmsh::plugin::setString("PluginName", "ParameterName", "value"); // 字符串参数
int newViewTag = gmsh::plugin::run("PluginName"); // 执行并返回新View标签
关键点:
- 参数名是大小写敏感的("Value" 不等于 "value")
- setNumber 和 setString 设置的是全局状态,run() 执行前所有参数必须设置完毕
- run() 返回新生成的 View 标签(整数),可用于后续的 view::option::setNumber() 调整显示属性
- 如果想覆盖已有 View 而非生成新 View,可设置参数 "View" 为负数(表示不生成新视图)
20.2.4 CAE 中的应用场景
- 截面应力云图:有限元求解得到3D应力场后,用 CutPlane/CutMap 截取关键截面(如螺栓孔剖面)的应力分布,用于强度校核报告
- 流场流线可视化:CFD 求解得到速度场后,用 StreamLines 追踪流体质点轨迹,辅助判断涡流、回流区域
- 等值面包络分析:用 Isosurface 提取温度场中某一温度值的包络面,判断热影响区范围
- 参数化分析:批量改变求解参数后,用 Probe 在固定监控点自动采样场值,绘制参数-响应曲线
20.3 C++ 代码逐段讲解
20.3.1 头文件与初始化
#include <set>
#include <cmath>
#include <vector>
#include <gmsh.h>
int main(int argc, char **argv)
{
gmsh::initialize(argc, argv);
gmsh::model::add("ch20_plugins");
解释:<set> 用于命令行参数判断(是否启动 GUI),<cmath> 提供 M_PI 等常量,<vector> 用于容纳节点和单元数据。gmsh::model::add() 为当前模型命名。
20.3.2 加载预置三维标量视图
// ---- 1. 加载 Gmsh 教程自带的 3D 标量场视图 ----
try {
gmsh::merge("../view3.pos");
} catch(...) {
gmsh::logger::write("Could not load post-processing views: bye!");
gmsh::finalize();
return 0;
}
std::vector<int> v;
gmsh::view::getTags(v);
if(v.size() != 1) {
gmsh::logger::write("Wrong number of views!", "error");
gmsh::finalize();
return 1;
}
解释:gmsh::merge() 加载后处理数据文件。view3.pos 是 Gmsh 教程提供的三维标量场(一个简单的结构应力模拟数据)。view::getTags() 获取当前模型中的所有 View 标签,此处预期只加载了一个 View。
使用 try-catch 包裹加载操作:.pos 文件可能不存在、格式损坏或路径错误,捕获异常后优雅退出是工程中的良好实践。
20.3.3 创建演示几何体与网格(用于构建矢量视图)
// ---- 2. 创建演示几何体并生成网格 ----
// 创建一个立方体作为矢量场的物理域
gmsh::model::occ::addBox(0, 0, 0, 2, 2, 2, 1);
gmsh::model::occ::synchronize();
gmsh::model::mesh::generate(3);
解释:创建一个 2x2x2 的立方体并生成三维四面体网格。这个网格将作为后续基于模型的视图(model-based view)的数据源——我们将从网格节点坐标计算矢量场值,构建一个旋转矢量场 v = (-y, x, 0),用于演示 StreamLines 插件。
20.3.4 从网格数据创建标量视图(Model-Based View)
// ---- 3. 创建基于模型的标量视图 (Model-Based View) ----
// 获取所有节点坐标
std::vector<std::size_t> nodeTags;
std::vector<double> nodeCoords, nodeParams;
gmsh::model::mesh::getNodes(nodeTags, nodeCoords, nodeParams, 3);
// 对每个节点计算标量值: f(x,y,z) = sqrt(x^2 + y^2) —— 到Z轴的距离
std::vector<double> scalarData;
for(std::size_t i = 0; i < nodeCoords.size(); i += 3) {
double d = std::sqrt(nodeCoords[i] * nodeCoords[i] +
nodeCoords[i + 1] * nodeCoords[i + 1]);
scalarData.push_back(d);
}
// 创建标量视图并填充 NodeData
int vScalar = gmsh::view::add("scalar_distance_to_z");
gmsh::view::addHomogeneousModelData(
vScalar, 0, // viewTag, step
"ch20_plugins", // modelName
"NodeData", // dataType: 节点数据 → 连续场
nodeTags, scalarData, // tags + data
0.0, // time
1); // numComponents = 1 (标量)
解释:这里展示了创建基于模型的视图(model-based view)的完整流程。mesh::getNodes() 获取所有三维节点(dim=3)的标签和坐标。对每个节点计算到 Z 轴的距离作为标量值,模拟一个轴对称的温度场或应力幅值场。
view::addHomogeneousModelData() 是该流程的核心 API:
- 参数 "NodeData" 表示数据定义在节点上(Gmsh 会用节点形函数进行连续插值)
- nodeTags 必须与 scalarData 按顺序一一对应
- numComponents=1 表示标量场;numComponents=3 表示矢量场;numComponents=9 表示张量场
20.3.5 从网格数据创建矢量视图(用于流线演示)
// ---- 4. 创建基于模型的矢量视图 ----
// 矢量场 v = (-y, x, 0) —— 绕 Z 轴的旋转场
std::vector<double> vectorData;
for(std::size_t i = 0; i < nodeCoords.size(); i += 3) {
double x = nodeCoords[i];
double y = nodeCoords[i + 1];
vectorData.push_back(-y); // vx
vectorData.push_back( x); // vy
vectorData.push_back( 0.0); // vz
}
int vVector = gmsh::view::add("vector_rotational");
gmsh::view::addHomogeneousModelData(
vVector, 0, "ch20_plugins", "NodeData",
nodeTags, vectorData,
0.0, // time
3); // numComponents = 3 (矢量)
解释:numComponents=3 将数据标记为矢量场。vectorData 的存储顺序为 vx1, vy1, vz1, vx2, vy2, vz2, ...(分量交错存储)。该旋转矢量场 v = (-y, x, 0) 在 XY 平面形成围绕 Z 轴的逆时针旋转,非常适合演示 StreamLines 插件的流线追踪效果。
20.3.6 Isosurface 等值面提取
// ---- 5. Isosurface 等值面提取 ----
// 从 view[0](view3.pos 加载的标量场)中提取 Value=0.67 的等值面
gmsh::plugin::setNumber("Isosurface", "Value", 0.67);
gmsh::plugin::setNumber("Isosurface", "View", 0); // View[0] 为数据源
int vIso = gmsh::plugin::run("Isosurface");
解释:Isosurface 插件在三维标量场中寻找所有等于 Value 的点的集合,并以曲面形式输出。"View" 参数指定源 View 的索引(注意:是索引号而非标签号——View[0] 指 view::getTags() 返回列表中的第一个标签)。
CAE 应用示例:在温度场中提取 T=800 摄氏度的等值面,判断热影响区(HAZ)边界。
20.3.7 CutPlane 截面与 CutMap 截面映射
// ---- 6. CutPlane 截面 ----
// 平面方程: A*x + B*y + C*z + D = 0
// 此处: 0*x + 0.2*y + 1*z + 0 = 0 → z = -0.2*y(倾斜平面)
gmsh::plugin::setNumber("CutPlane", "A", 0);
gmsh::plugin::setNumber("CutPlane", "B", 0.2);
gmsh::plugin::setNumber("CutPlane", "C", 1);
gmsh::plugin::setNumber("CutPlane", "D", 0);
gmsh::plugin::setNumber("CutPlane", "View", 0);
int vCut = gmsh::plugin::run("CutPlane");
// ---- 7. CutMap 2D 截面映射 ----
// 将标量场在 XY 平面 (z=0) 上的值展平为彩色二维图
gmsh::plugin::setNumber("CutMap", "A", 0);
gmsh::plugin::setNumber("CutMap", "B", 0);
gmsh::plugin::setNumber("CutMap", "C", 1);
gmsh::plugin::setNumber("CutMap", "D", -0.5); // z = 0.5
gmsh::plugin::setNumber("CutMap", "View", 0);
int vMap = gmsh::plugin::run("CutMap");
解释:
-
CutPlane:用任意位姿的平面
A*x + B*y + C*z + D = 0截取三维视图。向量(A, B, C)为平面法向,D控制平面沿法向的偏置距离。结果是一个二维截面上的场分布视图。 -
CutMap:与 CutPlane 类似,但将截面上的标量值"平展"为一张彩色的二维矩形图。截面位于
z = -D/C = 0.5。CutMap 比 CutPlane 更直观——它去除了三维透视效应,便于精确判读截面上的数值分布(如截面最大应力值的位置和大小)。
CutPlane vs CutMap 的工程选型: | 特性 | CutPlane | CutMap | |------|----------|--------| | 输出 | 3D 空间中的截面 | 展平的 2D 彩色图 | | 适用场景 | 综合性可视化 | 精确数值判读 | | 多截面叠加 | 可叠加显示 | 独立成图 |
20.3.8 Skin 表面提取
// ---- 8. Skin 表面提取 ----
// 从 Isosurface 的结果中提取外表面
gmsh::plugin::setNumber("Skin", "View", vIso);
int vSkin = gmsh::plugin::run("Skin");
解释:Skin 插件提取三维视图的外表面(outward-facing surface),去除内部结构。当源 View 是封闭等值面时,Skin 结果等于源 View 本身;当源 View 包含内部网格时,Skin 仅保留可见的外部面,可用于生成轻量化的外表面包络。
多插件串联示例:原始标量场 → Isosurface → Skin。这种串联是构建后处理流水线的核心模式。
20.3.9 StreamLines 流线追踪
// ---- 9. StreamLines 流线追踪 ----
// 从矢量视图中,在多个起点追踪流线
// 流线起点:在 XY 平面均匀分布 4 个种子点
for(int i = 0; i < 4; i++) {
double seedX = 1.0;
double seedY = 0.5 + i * 0.5;
double seedZ = 1.0;
gmsh::plugin::setNumber("StreamLines", "X0", seedX);
gmsh::plugin::setNumber("StreamLines", "Y0", seedY);
gmsh::plugin::setNumber("StreamLines", "Z0", seedZ);
gmsh::plugin::setString("StreamLines", "View", std::to_string(vVector));
gmsh::plugin::setNumber("StreamLines", "TimeStep", 0.05);
gmsh::plugin::setNumber("StreamLines", "MaxRecursion", 2000);
int vSL = gmsh::plugin::run("StreamLines");
}
解释:StreamLines 插件从指定的起始点 (X0, Y0, Z0) 出发,沿矢量场方向(前向和后向)追踪流线。核心参数:
- "TimeStep":积分步长,越小精度越高但计算量越大
- "MaxRecursion":最大积分步数,限制流线长度
- "View" 参数接受字符串形式的 View 标签(此处用 std::to_string 转换),而非索引
此处 4 个种子点沿 X=1 线均匀分布,由于矢量场是绕 Z 轴的旋转场,流线将呈现同心圆弧。
CAE 应用:在 CFD 速度场中放置种子点追踪流线,直观显示回流区、涡旋结构;在电磁场中追踪磁力线。
20.3.10 Probe 探针采样
// ---- 10. Probe 探针采样 ----
// 在指定坐标采样标量场和矢量场的值
gmsh::plugin::setNumber("Probe", "X", 1.0);
gmsh::plugin::setNumber("Probe", "Y", 0.5);
gmsh::plugin::setNumber("Probe", "Z", 1.0);
gmsh::plugin::setString("Probe", "View", std::to_string(vVector));
gmsh::plugin::run("Probe"); // 结果输出到终端控制台
解释:Probe 插件在指定空间坐标 (X, Y, Z) 处对源 View 进行采样,将结果(场值及到最近单元的距离)打印到终端控制台。采样使用源 View 的插值方法,因此 "NodeData" 类型的视图在任意点都有插值结果。
CAE 应用:在参数化分析中,在固定监控点(如焊点位置、最大应力预期位置)用 Probe 批量采样,配合脚本绘制参数-响应曲线。
20.3.11 ModifyComponents 分量变换与 Annotate 标注
// ---- 11. ModifyComponents 修改矢量分量 ----
// 将矢量场的三个分量交换:(vx, vy, vz) → (vy, vx, vz)
// 使用表达式映射: 新分量 = f(旧分量)
gmsh::plugin::setNumber("ModifyComponents", "View", vVector);
gmsh::plugin::setNumber("ModifyComponents", "NewView", -1);
gmsh::plugin::setString("ModifyComponents", "Expression0", "v1");
gmsh::plugin::setString("ModifyComponents", "Expression1", "v0");
gmsh::plugin::setString("ModifyComponents", "Expression2", "v2");
int vMod = gmsh::plugin::run("ModifyComponents");
// ---- 12. Annotate 文本标注 ----
gmsh::plugin::setString("Annotate", "Text", "Gmsh Plugin Demo");
gmsh::plugin::setNumber("Annotate", "X", 1.e5); // >99999 = 窗口居中
gmsh::plugin::setNumber("Annotate", "Y", 50);
gmsh::plugin::setString("Annotate", "Font", "Times-BoldItalic");
gmsh::plugin::setNumber("Annotate", "FontSize", 28);
gmsh::plugin::setString("Annotate", "Align", "Center");
gmsh::plugin::setNumber("Annotate", "View", 0);
gmsh::plugin::run("Annotate");
解释:
-
ModifyComponents:通过对原始分量应用数学表达式来生成新的矢量场。
v0,v1,v2是内置变量,代表源场的三个分量。Expression0 = "v1"表示新场 x 分量取源场 y 分量值,实现了分量交换。NewView = -1表示不创建新 View(就地覆盖)。支持任意数学表达式,如"sqrt(v0^2 + v1^2)"可提取矢量幅值。 -
Annotate:在指定窗口中添加文字标注。坐标
X > 99999是 Gmsh 的约定——表示窗口水平居中。"Center"对齐方式使文本以坐标点为中心。"View"参数指定标注添加到哪个 View 的显示中。
20.3.12 视图可视化选项与 GUI 启动
// ---- 13. 设置视图可视化选项 ----
// 对原始标量视图: 开启光照、等值线显示
gmsh::view::option::setNumber(v[0], "Light", 1);
gmsh::view::option::setNumber(v[0], "IntervalsType", 1); // 等值线
gmsh::view::option::setNumber(v[0], "NbIso", 6); // 6条等值线
gmsh::view::option::setNumber(v[0], "SmoothNormals", 1); // 法向光滑
// 对等值面和截面视图: 连续色带
gmsh::view::option::setNumber(vIso, "IntervalsType", 2); // 连续
gmsh::view::option::setNumber(vCut, "IntervalsType", 2);
// 对流线视图: 设置箭头大小
gmsh::view::option::setNumber(vVector, "ArrowSizeMax", 30);
gmsh::view::option::setNumber(vVector, "ShowScale", 0);
// 对 CutMap 视图: 显示标尺
gmsh::view::option::setNumber(vMap, "ShowScale", 1);
// ---- 14. 启动 GUI 查看结果 ----
std::set<std::string> args(argv, argv + argc);
if(!args.count("-nopopup")) gmsh::fltk::run();
gmsh::finalize();
return 0;
}
解释:view::option::setNumber(viewTag, optionName, value) 设置单个 View 的显示属性。常用选项:
| 选项名 | 含义 | 典型值 |
|---|---|---|
Light |
是否开启光照渲染 | 0=关闭, 1=开启 |
IntervalsType |
色带类型 | 1=等值线, 2=连续渐变, 3=离散色块 |
NbIso |
等值线条数 | 正整数 |
SmoothNormals |
法向量光滑(视觉) | 0=关闭, 1=开启 |
ShowScale |
是否显示色标尺 | 0=关闭, 1=开启 |
ArrowSizeMax |
矢量箭头最大尺寸(像素) | 正整数 |
ColormapNumber |
色图编号 | 0-22(共23种内置色图) |
通过 -nopopup 命令行参数可以跳过 GUI 直接执行插件(适用于批处理脚本)。
20.4 完整可运行代码
// =============================================================================
// Chapter 20: Post-Processing Plugins
//
// 功能: 演示 Gmsh 常用后处理插件的使用,包括等值面、切平面、
// 截面映射、表面提取、流线追踪、探针采样、分量变换和文本标注
//
// 编译 (需链接 Gmsh SDK):
// g++ -o ch20_plugins ch20_plugins.cpp -lgmsh -std=c++11
//
// 运行:
// ./ch20_plugins (带 GUI 交互查看)
// ./ch20_plugins -nopopup (仅运行插件,不启动 GUI)
//
// 依赖文件:
// view3.pos (Gmsh 教程自带的 3D 标量视图数据文件)
// =============================================================================
#include <set>
#include <cmath>
#include <vector>
#include <string>
#include <gmsh.h>
int main(int argc, char **argv)
{
gmsh::initialize(argc, argv);
gmsh::model::add("ch20_plugins");
// ===== 1. 加载预置 3D 标量视图 =====
try {
gmsh::merge("../view3.pos");
} catch(...) {
gmsh::logger::write("Could not load post-processing views: bye!");
gmsh::finalize();
return 0;
}
std::vector<int> v;
gmsh::view::getTags(v);
if(v.size() != 1) {
gmsh::logger::write("Wrong number of views!", "error");
gmsh::finalize();
return 1;
}
// ===== 2. 创建演示几何体与网格(用于构建矢量视图) =====
gmsh::model::occ::addBox(0, 0, 0, 2, 2, 2, 1);
gmsh::model::occ::synchronize();
gmsh::model::mesh::generate(3);
// ===== 3. 创建基于模型的标量视图 (Model-Based View) =====
std::vector<std::size_t> nodeTags;
std::vector<double> nodeCoords, nodeParams;
gmsh::model::mesh::getNodes(nodeTags, nodeCoords, nodeParams, 3);
std::vector<double> scalarData;
for(std::size_t i = 0; i < nodeCoords.size(); i += 3) {
double d = std::sqrt(nodeCoords[i] * nodeCoords[i] +
nodeCoords[i + 1] * nodeCoords[i + 1]);
scalarData.push_back(d);
}
int vScalar = gmsh::view::add("scalar_distance_to_z");
gmsh::view::addHomogeneousModelData(
vScalar, 0, "ch20_plugins", "NodeData",
nodeTags, scalarData, 0.0, 1);
// ===== 4. 创建基于模型的矢量视图 =====
std::vector<double> vectorData;
for(std::size_t i = 0; i < nodeCoords.size(); i += 3) {
double x = nodeCoords[i], y = nodeCoords[i + 1];
vectorData.push_back(-y); // vx
vectorData.push_back( x); // vy
vectorData.push_back( 0.0); // vz
}
int vVector = gmsh::view::add("vector_rotational");
gmsh::view::addHomogeneousModelData(
vVector, 0, "ch20_plugins", "NodeData",
nodeTags, vectorData, 0.0, 3);
// ===== 5. Isosurface 等值面提取 =====
gmsh::plugin::setNumber("Isosurface", "Value", 0.67);
gmsh::plugin::setNumber("Isosurface", "View", 0);
int vIso = gmsh::plugin::run("Isosurface");
// ===== 6. CutPlane 切平面 =====
gmsh::plugin::setNumber("CutPlane", "A", 0);
gmsh::plugin::setNumber("CutPlane", "B", 0.2);
gmsh::plugin::setNumber("CutPlane", "C", 1);
gmsh::plugin::setNumber("CutPlane", "D", 0);
gmsh::plugin::setNumber("CutPlane", "View", 0);
int vCut = gmsh::plugin::run("CutPlane");
// ===== 7. CutMap 2D 截面映射 =====
gmsh::plugin::setNumber("CutMap", "A", 0);
gmsh::plugin::setNumber("CutMap", "B", 0);
gmsh::plugin::setNumber("CutMap", "C", 1);
gmsh::plugin::setNumber("CutMap", "D", -0.5);
gmsh::plugin::setNumber("CutMap", "View", 0);
int vMap = gmsh::plugin::run("CutMap");
// ===== 8. Skin 表面提取 (从等值面结果) =====
gmsh::plugin::setNumber("Skin", "View", vIso);
int vSkin = gmsh::plugin::run("Skin");
// ===== 9. StreamLines 流线追踪 =====
for(int i = 0; i < 4; i++) {
gmsh::plugin::setNumber("StreamLines", "X0", 1.0);
gmsh::plugin::setNumber("StreamLines", "Y0", 0.5 + i * 0.5);
gmsh::plugin::setNumber("StreamLines", "Z0", 1.0);
gmsh::plugin::setString("StreamLines", "View", std::to_string(vVector));
gmsh::plugin::setNumber("StreamLines", "TimeStep", 0.05);
gmsh::plugin::setNumber("StreamLines", "MaxRecursion", 2000);
gmsh::plugin::run("StreamLines");
}
// ===== 10. Probe 探针采样 =====
gmsh::plugin::setNumber("Probe", "X", 1.0);
gmsh::plugin::setNumber("Probe", "Y", 0.5);
gmsh::plugin::setNumber("Probe", "Z", 1.0);
gmsh::plugin::setString("Probe", "View", std::to_string(vVector));
gmsh::plugin::run("Probe");
// ===== 11. ModifyComponents 分量变换 =====
gmsh::plugin::setNumber("ModifyComponents", "View", vVector);
gmsh::plugin::setNumber("ModifyComponents", "NewView", -1);
gmsh::plugin::setString("ModifyComponents", "Expression0", "v1");
gmsh::plugin::setString("ModifyComponents", "Expression1", "v0");
gmsh::plugin::setString("ModifyComponents", "Expression2", "v2");
int vMod = gmsh::plugin::run("ModifyComponents");
// ===== 12. Annotate 文本标注 =====
gmsh::plugin::setString("Annotate", "Text", "Gmsh Plugin Demo");
gmsh::plugin::setNumber("Annotate", "X", 1.e5);
gmsh::plugin::setNumber("Annotate", "Y", 50);
gmsh::plugin::setString("Annotate", "Font", "Times-BoldItalic");
gmsh::plugin::setNumber("Annotate", "FontSize", 28);
gmsh::plugin::setString("Annotate", "Align", "Center");
gmsh::plugin::setNumber("Annotate", "View", 0);
gmsh::plugin::run("Annotate");
// ===== 13. 视图可视化选项 =====
gmsh::view::option::setNumber(v[0], "Light", 1);
gmsh::view::option::setNumber(v[0], "IntervalsType", 1);
gmsh::view::option::setNumber(v[0], "NbIso", 6);
gmsh::view::option::setNumber(v[0], "SmoothNormals", 1);
gmsh::view::option::setNumber(vIso, "IntervalsType", 2);
gmsh::view::option::setNumber(vCut, "IntervalsType", 2);
gmsh::view::option::setNumber(vVector, "ArrowSizeMax", 30);
gmsh::view::option::setNumber(vVector, "ShowScale", 0);
gmsh::view::option::setNumber(vMap, "ShowScale", 1);
// ===== 14. 启动 GUI =====
std::set<std::string> args(argv, argv + argc);
if(!args.count("-nopopup")) gmsh::fltk::run();
gmsh::finalize();
return 0;
}
20.5 关键 API 速查表
| API | 函数签名 | 说明 |
|---|---|---|
plugin::setNumber |
(pluginName, paramName, value) |
设置插件的数值型参数(浮点数或整数) |
plugin::setString |
(pluginName, paramName, value) |
设置插件的字符串型参数 |
plugin::run |
(pluginName) → int |
执行插件,返回新生成的 View 标签(整数) |
view::add |
(viewName) → int |
创建一个新 View,返回其标签 |
view::getTags |
(tags) |
获取当前模型中的所有 View 标签列表 |
view::addHomogeneousModelData |
(viewTag, step, modelName, dataType, tags, data, time, numComp) |
添加基于模型的数据(均匀类型——所有元素节点数相同) |
view::addModelData |
(viewTag, step, modelName, dataType, tags, data, time, numComp, partition) |
添加基于模型的数据(支持混合网格——元素节点数可变化) |
view::addListData |
(viewTag, dataType, numElems, data) |
添加基于列表的数据(独立于网格,如 "ST"=标量三角形) |
view::option::setNumber |
(viewTag, optionName, value) |
设置单个 View 的可视化选项(如 Light, IntervalsType, NbIso) |
view::option::setString |
(viewTag, optionName, value) |
设置单个 View 的字符串选项 |
view::probe |
(viewTag, x, y, z, values, distance) |
在指定空间点探测 View 的场值(API 方式,不依赖插件) |
view::write |
(viewTag, filename) |
将 View 保存到 .pos 或 .msh 文件 |
model::mesh::getNodes |
(nodeTags, coord, param, dim, tag, includeBoundary) |
获取网格节点标签和坐标(dim=-1 获取所有维度的节点) |
gmsh::merge |
(filename) |
合并/加载外部文件(几何、网格或后处理视图) |
20.6 内置插件参数速查
Isosurface(等值面)
| 参数 | 类型 | 说明 |
|---|---|---|
Value |
number | 等值面的标量值 |
View |
number | 源 View 的索引号(非标签号),View[-1] 为当前 View |
ExtractVolume |
number | 是否提取体积(0=否, >0=是) |
CutPlane / CutMap(截面)
| 参数 | 类型 | 说明 |
|---|---|---|
A, B, C, D |
number | 平面方程系数: A*x + B*y + C*z + D = 0。(A,B,C) 为法向量 |
View |
number | 源 View 索引 |
RecurLevel |
number | 递归次数(用于自适应细分) |
StreamLines(流线)
| 参数 | 类型 | 说明 |
|---|---|---|
View |
string | 源 View 标签的字符串形式(如 "0") |
X0, Y0, Z0 |
number | 流线起始点坐标 |
TimeStep |
number | 积分步长 |
MaxRecursion |
number | 最大积分步数 |
Direction |
string | 追踪方向:"Forward", "Backward", "Both" |
Skin(表面提取)
| 参数 | 类型 | 说明 |
|---|---|---|
View |
number | 源 View 标签/索引 |
VisibleOnly |
number | 是否仅提取可见面(0=全部表面, 1=仅可见) |
Probe(探针)
| 参数 | 类型 | 说明 |
|---|---|---|
X, Y, Z |
number | 采样点坐标 |
View |
string | 源 View 标签的字符串形式 |
Interpolation |
number | 插值方法(0=默认) |
ModifyComponents(分量修改)
| 参数 | 类型 | 说明 |
|---|---|---|
View |
number | 源 View 标签 |
Expression0 ~ Expression9 |
string | 各分量的数学表达式。内置变量 v0~v8 代表源场分量 |
NewView |
number | -1=覆盖源View, 0=创建新View |
Annotate(文本标注)
| 参数 | 类型 | 说明 |
|---|---|---|
Text |
string | 文本内容 |
X, Y (2D), X, Y, Z (3D) |
number | 坐标位置(X>99999=窗口居中) |
Font |
string | 字体名(如 "Times-BoldItalic", "Helvetica") |
FontSize |
number | 字号 |
Align |
string | 对齐方式:"Left", "Center", "Right" |
View |
number | 目标 View 索引 |
20.7 本章小结
- View(视图) 是 Gmsh 后处理数据的容器,支持标量/矢量/张量场,分为 list-based(独立于网格)和 model-based(绑定到网格)两种。
- Plugin(插件) 对 View 进行运算或变换,通过
setNumber()/setString()配置参数,run()执行并生成新 View。 - 六大常用插件:Isosurface(等值面)、CutPlane(3D 截面)、CutMap(2D 截面图)、Skin(提取表面)、StreamLines(流线追踪)、Probe(探针采样)。
- 插件可以串联使用(如
标量场 → Isosurface → Skin),构建自动化后处理流水线。 view::addHomogeneousModelData()与view::addListData()分别是创建 model-based 和 list-based 视图的两种方式;前者绑定到网格,后者独立存在。view::option::setNumber()控制单个 View 的显示属性(光照、色带类型、等值线条数等),是生成出版级后处理图的关键。
20.8 注意事项
-
View 索引 vs 标签:
Isosurface、CutPlane、Annotate等插件的"View"参数使用索引号(从 0 开始),而StreamLines和Probe的"View"参数使用标签号的字符串形式。这是 Gmsh 插件接口的历史遗留不一致,使用时务必查阅对应插件的文档。 -
插件参数残留:
plugin::setNumber()和plugin::setString()设置的是全局状态。同一个插件的参数在前一次run()后仍保留。如果第二次调用同一插件但不重新设置全部参数,前次的参数值可能仍生效。建议每次run()前显式设置所有关键参数。 -
IntervalsType含义:1=等值线(iso-lines, 连续曲线),2=连续色带(continuous, 渐变色填充),3=离散色块(discrete, 按区间分段着色)。选择不当可能导致视图在 GUI 中完全不可见。 -
StreamLines 的 View 参数:该插件的
"View"参数类型为string(字符串),而非number。如果用setNumber()设置将不会生效。必须使用setString()并传入标签的字符串形式。 -
Probe 的输出:
Probe插件将结果打印到 Gmsh 日志/终端,如果需要编程方式获取采样值,应使用view::probe()API 而非 Probe 插件。详见 x3.cpp 中的gmsh::view::probe()用法。 -
model-based view 对网格变化的响应:model-based view 依赖网格拓扑。如果后续对几何做
fragment、removeEntities等改变网格的操作,之前创建的 model-based view 数据可能失效(节点/单元标签不再对应)。应在网格最终确定后再创建 model-based views。 -
插件结果的 View 标签管理:
plugin::run()每次调用都生成新 View(标签递增)。在批量运行时如不管理,会累积大量 View。可通过设置"View"为负数使插件覆盖指定 View,或定期调用view::remove()清理不需要的 View。