本期开始带着大家学习开源项目 Mesh2D[1]。它是一个基于 MATLAB 的二维 Delaunay 网格生成器(mesh-generator),专门为通用二维几何体生成高质量的非结构化三角形网格。其核心用途和特点包括:
先来操作一下,简单的几何区域及网格参数设置:
node = [
0, 0; 9, 0; 9, 9; 0, 9; % 外部
4, 4; 5, 4; 5, 5; 4, 5% 内部孔
];
edge = [
1, 2; 2, 3; 3, 4; 4, 1; % 外部
5, 6; 6, 7; 7, 8; 8, 5% 内部
];
[vert, etri, tria, tnum] = refine2(node, edge);
绘制原始边界和新生成的mesh
patch('faces', tria(:,1:3), 'vertices', vert, ...
'facecolor', 'w', 'edgecolor', [.2,.2,.2]);
hold on; axis image off;
patch('faces', edge(:,1:2), 'vertices', node, ...
'facecolor', 'w', 'edgecolor', [.1,.1,.1], 'linewidth', 1.5);
hfun 控制单元边长,作为输入参数的第五个位置,目前为常数,后续自定义密度函数时在做详细介绍。
hfun = 0.3; % 变小则更密,变大则更粗
[vert, etri, tria, tnum] = refine2(node, edge, [], [], hfun);
node = [
0, 0; 9, 0; 9, 9; 0, 9; % 外部
4, 4; 5, 4; 5, 5; 4, 5% 内部孔
];
edge = [
1, 2; 2, 3; 3, 4; 4, 1; % 外部
5, 6; 6, 7; 7, 8; 8, 5% 内部
];
figure;
subplot(1,2,1)
[vert, etri, tria, tnum] = refine2(node, edge);
patch('faces', tria(:,1:3), 'vertices', vert, ...
'facecolor', 'w', 'edgecolor', [.2,.2,.2]);
hold on; axis image off;
patch('faces', edge(:,1:2), 'vertices', node, ...
'facecolor', 'w', 'edgecolor', [.1,.1,.1], 'linewidth', 1.5);
title('基础 mesh');
subplot(1,2,2)
hfun = 0.3;
[vert, etri, tria, tnum] = refine2(node, edge, [], [], hfun);
patch('faces', tria(:,1:3), 'vertices', vert, ...
'facecolor', 'w', 'edgecolor', [.2,.2,.2]);
hold on; axis image off;
patch('faces', edge(:,1:2), 'vertices', node, ...
'facecolor', 'w', 'edgecolor', [.1,.1,.1], 'linewidth', 1.5);
title(['加密 mesh, hfun = ', num2str(hfun)]);
经过上面案例的学习,是不是对基础的网格划分方法有了一定的认识,现在我们再来试试变换一下几何区域:
% ==== 外正方形节点和边 ====
node = [00; 90; 99; 09];
edge = [12; 23; 34; 41];
% ==== 圆孔节点和边 ====
N = 32; % 圆孔离散点数,越多越圆滑
r = 1; % 圆半径
cx = 4.5; cy = 4.5; % 圆心
theta = linspace(0, 2*pi, N+1)';
theta(end) = []; % 去除最后一个和第一个重合
circle_nodes = [cx + r*cos(theta), cy + r*sin(theta)];
circle_edges = [(1:N)' [2:N 1]']; % 连环相接
% ==== 拼接 ====
node = [node; circle_nodes];
edge = [edge; (4+(1:N))' (4+[2:N 1])'];
% ==== 外正方形节点和边 ====
node = [00; 90; 99; 09];
edge = [12; 23; 34; 41];
% ==== 圆孔节点和边 ====
N = 32; % 圆孔离散点数,越多越圆滑
r = 1; % 圆半径
cx = 4.5; cy = 4.5; % 圆心
theta = linspace(0, 2*pi, N+1)';
theta(end) = []; % 去除最后一个和第一个重合
circle_nodes = [cx + r*cos(theta), cy + r*sin(theta)];
circle_edges = [(1:N)' [2:N 1]']; % 连环相接
% ==== 拼接 ====
node = [node; circle_nodes];
edge = [edge; (4+(1:N))' (4+[2:N 1])'];
% ==== mesh 生成 ====
hfun = 0.25; % 可以试试 0.1, 0.5
[vert, etri, tria, tnum] = refine2(node, edge, [], [], hfun);
figure;
patch('faces', tria(:,1:3), 'vertices', vert, ...
'facecolor', 'w', 'edgecolor', [.2,.2,.2]);
hold on; axis image off;
patch('faces', edge(:,1:2), 'vertices', node, ...
'facecolor', 'w', 'edgecolor', 'r', 'linewidth', 1.2);
title(['正方形带圆孔, hfun = ', num2str(hfun)]);
再来换种形式:
% ==== 外正方形 ====
node = [0,0; 9,0; 9,9; 0,9];
% ==== 添加两个圆孔 ====
N = 24;
r = 0.8;
theta = linspace(0, 2*pi, N+1)';
theta(end) = [];
% 孔1
c1 = [2.52.5];
circ1 = c1 + r*[cos(theta) sin(theta)];
% 孔2
c2 = [6.56.5];
circ2 = c2 + r*[cos(theta) sin(theta)];
node = [node; circ1; circ2];
edge = [12; 23; 34; 41; ... % 外部
(4+(1:N))' (4+[2:N 1])'; ... % 孔1
(4+N+(1:N))' (4+N+[2:N 1])']; % 孔2
% ==== 外正方形 ====
node = [0,0; 9,0; 9,9; 0,9];
% ==== 添加两个圆孔 ====
N = 24;
r = 0.8;
theta = linspace(0, 2*pi, N+1)';
theta(end) = [];
% 孔1
c1 = [2.52.5];
circ1 = c1 + r*[cos(theta) sin(theta)];
% 孔2
c2 = [6.56.5];
circ2 = c2 + r*[cos(theta) sin(theta)];
node = [node; circ1; circ2];
edge = [12; 23; 34; 41; ... % 外部
(4+(1:N))' (4+[2:N 1])'; ... % 孔1
(4+N+(1:N))' (4+N+[2:N 1])']; % 孔2
hfun = 0.22;
[vert, etri, tria, tnum] = refine2(node, edge, [], [], hfun);
figure;
set(gcf,'color','white');
patch('faces', tria(:,1:3), 'vertices', vert, ...
'facecolor', 'w', 'edgecolor', [.2,.2,.2]);
hold on; axis image off;
patch('faces', edge(:,1:2), 'vertices', node, ...
'facecolor', 'w', 'edgecolor', 'm', 'linewidth', 1.2);
title('双孔正方形 mesh');