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

如何用Python实现相交网格的穿透量测量并导出VTK文件?

解决网格穿透量测量问题

你的核心问题是cKDTree计算的是无符号欧氏距离,只能得到点到另一个网格的最近距离大小,无法区分点是否处于另一个网格的内部(穿透区域)。要实现区分穿透和外部距离,需要计算有符号距离场——将处于目标网格内部的点的距离设为负值,外部设为正值。

实现思路

  • 用cKDTree计算mesh2每个点到mesh1的最小距离(绝对值)
  • 判断mesh2的每个点是否处于mesh1的内部
  • 对内部点的距离取负,得到带符号的距离(负值表示穿透,正值表示外部距离)
  • 将带符号的距离作为标量字段保存到VTK文件,实现穿透量着色

修改后的代码

#!/usr/bin/env python3

import numpy as np
import pyvista as pv

# Paths to meshes
mesh1_path = "/path/to/mesh1.stl"
mesh2_path = "/path/to/mesh2.stl"

# Read meshes
mesh1 = pv.read(mesh1_path)
mesh2 = pv.read(mesh2_path)

# --------------------------
# 计算带符号的距离(核心修改)
# --------------------------
fieldname = "signed_distance"
dist_mesh = mesh2

# 1. 计算mesh2每个点到mesh1的最小欧氏距离(绝对值)
from scipy.spatial import cKDTree
tree = cKDTree(mesh1.points)
d_kdtree, idx = tree.query(dist_mesh.points)

# 2. 判断mesh2的点是否在mesh1内部
# 注意:mesh1必须是封闭的STL模型,否则contains判断会出错
is_inside = mesh1.contains(dist_mesh.points)

# 3. 生成带符号的距离:内部点距离取负,外部点保持正值
signed_d = np.where(is_inside, -d_kdtree, d_kdtree)
dist_mesh[fieldname] = signed_d

# 可视化:用带符号的距离着色,负值(穿透)会显示为冷色调,正值为暖色调
plotter = pv.Plotter()
# 设置颜色范围包含正负值,确保穿透区域清晰显示
clim = [np.min(signed_d), np.max(signed_d)]
plotter.add_mesh(dist_mesh, clim=clim, scalars=fieldname,
                 smooth_shading=True, opacity=1, cmap="jet")
plotter.show()

# 保存带符号距离的VTK文件
dist_mesh.save(f"/tmp/{fieldname}.vtk")

关键细节说明

  • 网格封闭性:mesh1.contains()方法依赖封闭的多边形网格,STL模型通常满足这个要求。如果网格有缺口或非封闭,内部点判断会不准确,此时可以调整pyvista.point_in_mesh()的射线法参数来优化。
  • 距离精度:cKDTree基于点云计算距离,若mesh1的面密度较低,最近点距离可能和实际面距离有偏差。如果需要更高精度的面距离,可以改用PyVista的compute_implicit_distance()方法,直接计算点到网格表面的有符号距离。
  • 性能优化:对于大规模网格,contains()方法可能较慢,可以考虑先对mesh1进行简化,或者使用空间划分加速内部点判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:31:18