You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

曲面上下切片点排序算法: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()

关键优化点

  1. 调用extract_feature_edges直接提取有序的截面外轮廓点,避免手动排序打乱点的空间顺序
  2. 增加数值容差处理后缘点,弦线计算更准确
  3. 拆分上下点集后单独按X排序,绘制时不会出现交叉折线
  4. 增加plt.axis('equal')设置,避免翼型轮廓被拉伸变形

内容的提问来源于stack exchange,提问作者Miro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:54:01