PyVista 光线追踪仅检测一个交叉点

pyvista ray trace detects only one intersection

提问人:Bulbasaur 提问时间:8/31/2023 最后编辑:Bulbasaur 更新时间:10/21/2023 访问量:171

问:

我尝试使用 pyvista 检测射线与多边形的交点。在本例中,多边形是一个立方体。立方体由 2d 中的点定义,然后拉伸。为什么这个光线与立方体相交的简单示例只检测到一个相交点?

import numpy as np
import pyvista as pv

points = [(0, 0), (0, 10), (10, 10), (10, 0)]

def points_2d_to_poly(points, z):
        """Convert a sequence of 2d coordinates to polydata with a polygon."""
        faces = [len(points), *range(len(points))]
        poly = pv.PolyData([p + (z,) for p in points], faces=faces)
        return poly

polygon = points_2d_to_poly(points, 0.0)
polygon_extruded = polygon.extrude((0, 0, 6.0), capping=True)
poly_surface = polygon_extruded.extract_surface()
poly_mesh = poly_surface.triangulate()

# Define line segment
start = [5, 2, -10]
stop = [5, 2, 10]

# Perform ray trace
points, ind = poly_mesh.ray_trace(start, stop, first_point=False)

# Create geometry to represent ray trace
ray = pv.Line(start, stop)
intersection = pv.PolyData(points)

# Render the result
p = pv.Plotter()
p.add_mesh(poly_mesh, show_edges=True, opacity=0.5, color="w", lighting=False, label="Test Mesh")
p.add_mesh(ray, color="blue", line_width=5, label="Ray Segment")
p.add_mesh(intersection, color="maroon", point_size=25, label="Intersection Points")
p.add_legend()
p.show()
python vtk pyvista

评论

1赞 Andras Deak -- Слава Україні 9/1/2023
你得到什么结果?我看到它确实在原始与立方体的交集上,考虑到立方体的边界是 .因此,基于此,我认为这是成功的。你会得到不同的结果吗?points = np.array([[5., 2., 6.]], dtype=float32)[0, 10, 0, 10, 6, 12]
1赞 Bulbasaur 9/1/2023
你好。感谢您抽出宝贵时间接受采访。我在最初为该问题发布的代码中犯了一个错误。我更新了它 - 请再次运行它。请注意,立方体的几何形状已更改,光线与立方体相交两次。问题是ray_trace函数只检测到一个交叉点,而不是我预期的两个交叉点。只有当我希望被包括在内时,我才会得到。points = array([[5., 2., 0.]], dtype=float32)[5., 2., 6.]
1赞 Andras Deak -- Слава Україні 9/2/2023
我以前没有真正使用过光线追踪,但我找不到任何问题。您更新的示例看起来确实应该返回这两个点。在引擎盖下使用,其中一个版本说“返回指定线段与 OBB 树的第一个交点”。这听起来像是它不应该返回多个交叉点,但在这个官方示例中,它工作正常。ray_trace()vtkOBBTree.IntersectWithLine()
1赞 Andras Deak -- Слава Україні 9/2/2023
在我们使用它之前,我还尝试弄乱了 OBB 树的方法(为此我不得不编辑我的 PyVista 本地副本),但更改范围内的容差似乎并没有改变任何事情。在PyVista问题跟踪器上提出这个问题可能是值得的。SetTolerance()[1e-15, 1]
1赞 Matthew Flamm 10/20/2023
也不确定。如果由于某种原因这不健壮,则使用不同的 vtk 类,并且可以扩展以另外返回交点。github.com/pyvista/pyvista/blob/......find_cells_intersecting_line

答:

2赞 Matthew Flamm 10/21/2023 #1

poly_mesh缺少法线,根据所使用的 VTK 方法的文档,这是必需的。https://vtk.org/doc/nightly/html/classvtkAbstractCellLocator.html#a027818794762a37868a3dccc53ad6e81

此方法假定数据集是描述闭合表面的 vtkPolyData,并且在“点”中返回的交点在入口点和出口点之间交替。

因此,如果先计算法线,它将按预期工作。

import numpy as np
import pyvista as pv

points = [(0, 0), (0, 10), (10, 10), (10, 0)]

def points_2d_to_poly(points, z):
        """Convert a sequence of 2d coordinates to polydata with a polygon."""
        faces = [len(points), *range(len(points))]
        poly = pv.PolyData([p + (z,) for p in points], faces=faces)
        return poly

polygon = points_2d_to_poly(points, 0.0)
polygon_extruded = polygon.extrude((0, 0, 6.0), capping=True)
poly_surface = polygon_extruded.extract_surface()
# Note this line and following line are the only changes
poly_mesh = poly_surface.triangulate().compute_normals()

# Define line segment
start = [5, 2, -10]
stop = [5, 2, 10]

# Perform ray trace
points, ind = poly_mesh.ray_trace(start, stop, first_point=False)

# Create geometry to represent ray trace
ray = pv.Line(start, stop)
intersection = pv.PolyData(points)

# Render the result
p = pv.Plotter()
p.add_mesh(poly_mesh, show_edges=True, opacity=0.5, color="w", lighting=False, label="Test Mesh")
p.add_mesh(ray, color="blue", line_width=5, label="Ray Segment")
p.add_mesh(intersection, color="maroon", point_size=25, label="Intersection Points")
p.add_legend()
p.show()

评论

1赞 Matthew Flamm 10/21/2023
对于pyvista方法来说,最好先检查这一点,如果不可用,则计算法线,但在此之前可以使用此处的答案。ray_trace