曲面上下切片点排序算法:PyVista处理STL切片点分组问题
翼型截面拆分方案
核心问题说明
原代码的问题在于直接将截面原始点按X坐标排序后用弦线判断上下,直接按排序后的顺序绘制上下点导致连线顺序混乱,出现交叉折线。且PyVista切片结果自带有序边界信息,无需手动打乱点序。
优化后实现代码
import pyvista as pv import matplotlib.pylab as plt import numpy as np import math mesh = pv.read('wing_fish.stl') # 沿Z轴切指定高度截面 single_slice = mesh.slice(normal=[0,0,1], origin=[0,0,200]) # 提取截面的有序外轮廓点,过滤掉内部无关边 contour = single_slice.extract_feature_edges( boundary_edges=True, non_manifold_edges=False, manifold_edges=False, feature_edges=False ) points = contour.points[:, :2] # 仅保留XY坐标 # 计算弦线端点:前缘为X最小的点 front_idx = np.argmin(points[:,0]) x0, y0 = points[front_idx] # 后缘取X最大值附近的两个点的中点,容差适配数值精度 x_max = np.max(points[:,0]) tail_points = points[np.where(points[:,0] > x_max - 1e-3)] xc_end, yc_end = np.mean(tail_points, axis=0) mid_line = np.array([[x0, y0], [xc_end, yc_end]]) # 计算点在弦线的上下侧:返回值<0为下,>0为上,=0在线上 def get_line_side(p, x0, y0, x1, y1): return (y1 - y0) * (p[0] - x0) - (x1 - x0) * (p[1] - y0) # 拆分上下点集 upper = [] lower = [] for p in points: side = get_line_side(p, x0, y0, xc_end, yc_end) if abs(side) < 1e-6: continue elif side < 0: lower.append(p) else: upper.append(p) # 上下点集分别按X坐标排序,保证绘制顺序沿弦线从左到右 lower = np.array(lower) lower = lower[lower[:,0].argsort()] upper = np.array(upper) upper = upper[upper[:,0].argsort()] # 绘图 plt.plot(lower[:,0], lower[:,1], label='下部点') plt.plot(upper[:,0], upper[:,1], label='上部点') plt.plot(mid_line[:,0], mid_line[:,1], label='弦线') plt.scatter(points[:,0], points[:,1], label='原始点', s=10, c='gray') plt.legend() plt.grid() plt.axis('equal') # 保证翼型比例不变形 plt.show()
关键优化点
- 调用
extract_feature_edges直接提取有序的截面外轮廓点,避免手动排序打乱点的空间顺序 - 增加数值容差处理后缘点,弦线计算更准确
- 拆分上下点集后单独按X排序,绘制时不会出现交叉折线
- 增加
plt.axis('equal')设置,避免翼型轮廓被拉伸变形
内容的提问来源于stack exchange,提问作者Miro
相关产品推荐
相关产品推荐

