在Python中使用VTK查找3D空间中的两个圆柱的交点

时间:2019-03-04 09:59:06

标签: python mesh vtk raytracing

在python中使用VTK,我编写了一些代码来为我想要的对象创建actor,例如对于气缸:

def cylinder_object(startPoint, endPoint, radius, my_color="DarkRed"):
    USER_MATRIX = True
    colors = vtk.vtkNamedColors()

    cylinderSource = vtk.vtkCylinderSource()
    cylinderSource.SetRadius(radius)
    cylinderSource.SetResolution(50)

    rng = vtk.vtkMinimalStandardRandomSequence()
    rng.SetSeed(8775070)  # For testing.8775070

    # Compute a basis
    normalizedX = [0] * 3
    normalizedY = [0] * 3
    normalizedZ = [0] * 3

    # The X axis is a vector from start to end
    vtk.vtkMath.Subtract(endPoint, startPoint, normalizedX)
    length = vtk.vtkMath.Norm(normalizedX)
    vtk.vtkMath.Normalize(normalizedX)

    # The Z axis is an arbitrary vector cross X
    arbitrary = [0] * 3
    for i in range(0, 3):
        rng.Next()
        arbitrary[i] = rng.GetRangeValue(-10, 10)
    vtk.vtkMath.Cross(normalizedX, arbitrary, normalizedZ)
    vtk.vtkMath.Normalize(normalizedZ)

    # The Y axis is Z cross X
    vtk.vtkMath.Cross(normalizedZ, normalizedX, normalizedY)
    matrix = vtk.vtkMatrix4x4()
    # Create the direction cosine matrix
    matrix.Identity()
    for i in range(0, 3):
        matrix.SetElement(i, 0, normalizedX[i])
        matrix.SetElement(i, 1, normalizedY[i])
        matrix.SetElement(i, 2, normalizedZ[i])
    # Apply the transforms
    transform = vtk.vtkTransform()
    transform.Translate(startPoint)  # translate to starting point
    transform.Concatenate(matrix)  # apply direction cosines
    transform.RotateZ(-90.0)  # align cylinder to x axis
    transform.Scale(1.0, length, 1.0)  # scale along the height vector
    transform.Translate(0, .5, 0)  # translate to start of cylinder

    # Transform the polydata
    transformPD = vtk.vtkTransformPolyDataFilter()
    transformPD.SetTransform(transform)
    transformPD.SetInputConnection(cylinderSource.GetOutputPort())

    # Create a mapper and actor for the arrow
    mapper = vtk.vtkPolyDataMapper()
    actor = vtk.vtkActor()
    if USER_MATRIX:
        mapper.SetInputConnection(cylinderSource.GetOutputPort())
        actor.SetUserMatrix(transform.GetMatrix())
    else:
        mapper.SetInputConnection(transformPD.GetOutputPort())
    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(colors.GetColor3d(my_color))
    return actor

此函数返回一个actor,稍后我可以使用vtkRender对其进行渲染。 现在我想要的是首先找到两个给定的圆柱体Actors是否相交,然后找到相交点。 我可以在圆柱上使用vtkTriangleFilter并使用vtkOBBTree和射线投射来确定相交是否发生?

这里有两个相交的定向圆柱体: Intersected Cylinders

1 个答案:

答案 0 :(得分:1)

首先,您需要处理vtkPolyData对象(即几何图形),而不是vtkActor。您可能需要使用vtkTransformPolyDataFilter输出作为您的vtkPolyData(就像在else语句-示例here中所做的那样),而不是调用setUserMatrix。

您可以使用vtkBooleanOperationPolyDataFilter:可以找到一个示例here(在C ++中,但我相信它会有所帮助)和here(在Python中)。如果生成的几何不为空,则圆柱相交。

如果它不满足您的需求,则可以使用vtkImplicitModeller将圆柱体从多数据转换为图像数据(图像体积,体素);则可以更轻松,更准确地计算相交体积(可以使用vtkImageLogic)。您还可以使用vtkFlyingEdges3DvtkMarchingCubes的快速版本)将交集转换回vtkPolyData。

编辑:如注释中所讨论,因为有许多圆柱体,执行时间是一个问题。您可以尝试通过计算每对圆柱体的轴之间的距离来检测它们是否相交,以尝试优化过程,如遇此情况,请按照此答案的第一部分所述计算相交。我的想法如下:计算段之间的最短距离(here中描述了一种方法,还有段距的c ++代码,这就是您所需要的)。将距离与两个圆柱体的半径之和进行比较,如果比较短,则计算交点。