当Delaunay函数失效时,如何对MATLAB网格进行三角剖分?
嘿,我来帮你搞清楚这个MATLAB三角剖分的问题~
问题根源:
surf和delaunay的本质差异 你遇到的核心问题,是没搞明白这两个函数处理网格的逻辑完全不一样:
surf是基于结构化网格工作的:你用meshgrid生成的x,y,z是二维数组,本身就自带了网格的拓扑关系——每个点和周围四个点的连接规则都被隐含在数组的行列结构里。所以surf直接就能按照原网格的四边形面来绘制,不需要额外做剖分。delaunay(x,y,z)是对三维散点做体积剖分:它会自动把你的二维x,y,z数组拉成一维散点集合,然后试图构建一个包裹所有点的凸包并做全空间三角剖分。但你的圆环面是闭合的非凸曲面,这种散点式的三维剖分不仅会把曲面内部填满错误的三角面,甚至会因为点的环形分布出现混乱的连接,完全不是你想要的曲面剖分结果。
正确获取曲面三角剖分
TRI的方法 你需要的是匹配结构化网格拓扑的曲面三角剖分,而非三维散点的体积剖分,这里有三种靠谱的方法:
方法1:直接从surf对象提取现成的剖分数据
既然surf内部已经做好了正确的剖分,我们直接把它拿出来用就行:
% 先生成surf对象并绘图 h = surf(x,y,z,'EdgeAlpha',0.1); view([-52,64]) set(gca,'Color','none','Box','off') axis off % 提取内部生成的三角剖分矩阵TRI TRI = h.FaceVertexData; % 用提取的TRI单独绘图(可选) figure trisurf(TRI,x,y,z,'EdgeAlpha',0.1) view([-52,64]) set(gca,'Color','none','Box','off') axis off
方法2:手动构建结构化网格的三角剖分
因为你的网格是N×N的结构化网格,每个四边形面可以拆成两个三角形,我们可以手动生成符合拓扑的TRI矩阵,还能处理圆环面的环形边界:
% 生成结构化网格的顶点索引矩阵 [rows, cols] = size(x); idx = reshape(1:rows*cols, rows, cols); % 遍历每个四边形面,拆成两个三角形 TRI = []; for i = 1:rows-1 for j = 1:cols-1 % 第一个三角形:(i,j) → (i+1,j) → (i,j+1) TRI = [TRI; idx(i,j), idx(i+1,j), idx(i,j+1)]; % 第二个三角形:(i+1,j) → (i+1,j+1) → (i,j+1) TRI = [TRI; idx(i+1,j), idx(i+1,j+1), idx(i,j+1)]; end end % 处理圆环面的环形边界(最后一列和第一列点重合) for i = 1:rows-1 TRI = [TRI; idx(i,cols), idx(i+1,cols), idx(i,1)]; TRI = [TRI; idx(i+1,cols), idx(i+1,1), idx(i,1)]; end % 用生成的TRI绘图 trisurf(TRI,x,y,z,'EdgeAlpha',0.1) view([-52,64]) set(gca,'Color','none','Box','off') axis off
方法3:在参数空间做二维剖分再映射到三维
你的圆环面是参数化曲面(基于u,v生成),可以先在平面参数空间做Delaunay剖分,再映射到三维空间:
% 在参数空间(u,v)做二维Delaunay剖分 TRI_u_v = delaunay(u,v); % 将参数空间的剖分索引映射到三维顶点的索引 TRI = reshape(1:N*N,N,N); TRI = TRI(TRI_u_v); % 绘图验证 trisurf(TRI,x,y,z,'EdgeAlpha',0.1) view([-52,64]) set(gca,'Color','none','Box','off') axis off
内容的提问来源于stack exchange,提问作者zlon
相关产品推荐
相关产品推荐

