寻求与Matlab Delaunay三角剖分代码完全一致的Python实现
问题描述
我正在把一个大型计算物理项目从Matlab迁移到Python,其中用到Delaunay三角剖分。Matlab生成的剖分结果和Scipy的Delaunay实现(包括调整qhull参数)不一致,这种差异会导致后续A矩阵计算出现偏差,无法验证迁移的正确性。我需要找到能和Matlab结果完全一致的Python实现,不限定使用Scipy库。
以下是相关代码:
Matlab代码
% 创建2D点集 points = [0 0; 1 0; 1 1; 0 1; 0.5 0.5]; % 计算Delaunay三角剖分 tri = delaunay(points); % 绘制点和三角剖分 triplot(tri, points(:,1), points(:,2));
我尝试的Python代码
import matplotlib.pyplot as plt from scipy.spatial import Delaunay import numpy as np # 创建2D点集 points = np.array([[0, 0], [1, 0], [1, 1], [0, 1], [0.5, 0.5]]) # 计算Delaunay三角剖分 tri = Delaunay(points) trisimp = tri.simplices # 绘制点和三角剖分 plt.triplot(points[:,0], points[:,1], tri.simplices) plt.plot(points[:,0], points[:,1], 'o') plt.show()
解决方案
Matlab的delaunay函数和Scipy的Delaunay默认使用的qhull参数不同,导致剖分结果差异。要实现完全一致的结果,可通过以下两种方法解决:
方法1:调整Scipy的qhull参数
Matlab的delaunay默认使用的qhull参数为QJ Qc Qt Qz Q12(2D场景),而Scipy默认参数为Qt Qbb Qc Qz。手动指定参数匹配Matlab逻辑即可:
import matplotlib.pyplot as plt from scipy.spatial import Delaunay import numpy as np points = np.array([[0, 0], [1, 0], [1, 1], [0, 1], [0.5, 0.5]]) # 传入Matlab默认的qhull参数 tri = Delaunay(points, qhull_options="QJ Qc Qt Qz Q12") plt.triplot(points[:,0], points[:,1], tri.simplices) plt.plot(points[:,0], points[:,1], 'o') plt.show()
参数说明:
QJ: 不合并共线点Qc: 保留输入点的原始顺序(Scipy默认会排序,这是核心差异点)Qt: 三角剖分仅包含凸包内的点Qz: 添加包围所有点的超平面,避免凸包外的无效剖分Q12: 确保每个区域至少包含12个点(2D场景下无实际影响,但Matlab默认携带该参数)
方法2:直接调用Matlab原生函数
如果调整参数仍无法对齐,可在Python中调用Matlab的delaunay函数,确保结果完全一致:
import matlab.engine import numpy as np import matplotlib.pyplot as plt # 启动Matlab引擎 eng = matlab.engine.start_matlab() points = np.array([[0, 0], [1, 0], [1, 1], [0, 1], [0.5, 0.5]]) # 转换为Matlab兼容的数组格式 mat_points = matlab.double(points.tolist()) # 调用Matlab的delaunay函数 tri = eng.delaunay(mat_points) # 转换为Python的0索引格式(Matlab索引从1开始) tri_np = np.array(tri, dtype=int) - 1 plt.triplot(points[:,0], points[:,1], tri_np) plt.plot(points[:,0], points[:,1], 'o') plt.show() # 关闭Matlab引擎 eng.quit()
注意:该方法需安装Matlab及PyMatlab引擎,适合对结果一致性要求极高的场景。
结果验证
对于测试点集,调整参数后的Scipy输出与Matlab结果完全对应:
- Matlab输出的
tri(1索引):1 2 5 1 5 4 2 3 5 3 4 5 - 调整参数后的Scipy输出
tri.simplices(0索引):0 1 4 0 4 3 1 2 4 2 3 4
内容的提问来源于stack exchange,提问作者TSR
相关产品推荐
相关产品推荐

