使用Python中VTK来在三维空间内找到两个圆柱的交点

3

使用Python中的VTK,我编写了一些代码来为我想要的对象创建一个演员,例如圆柱体:

Original Answer翻译成"最初的回答"

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

这个函数可以返回一个演员,我可以使用 vtkRender 后来呈现它。 现在,我想首先找到两个给定圆柱的Actors是否相交,其次是找到交点。 我能否在我的圆柱上使用vtkTriangleFilter,并使用vtkOBBTree和射线投射来查找是否发生了交集?
这里有两个方向的圆柱相交: Intersected Cylinders
1个回答

1
首先,您需要处理vtkPolyData对象(即几何图形),而不是vtkActor。您可能需要使用vtkTransformPolyDataFilter输出作为您的vtkPolyData(就像在else语句中所做的那样 - 示例here),而不是调用setUserMatrix。
您可以使用vtkBooleanOperationPolyDataFilter:可以在here(用C++编写,但我相信它会有所帮助)和here(用Python编写)找到示例。如果生成的几何图形不为空,则圆柱体相交。
如果它不能满足您的需求,您可以使用vtkImplicitModeller将圆柱体从polydata转换为imagedata(图像体积,体素),然后计算交集体积会更容易和更准确(您可以使用vtkImageLogic)。您还可以使用vtkFlyingEdges3DvtkMarchingCubes的快速版本)将交集转换回vtkPolyData。

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


谢谢你的回答。我尝试了第一种方法来处理球体,但我不知道它是否适用于有方向的圆柱体。另外,我需要在每次迭代中检查一个圆柱体与其他大约20000个圆柱体的相交情况,所以这样做的速度够快吗? - shahriar
哎呀,如果执行时间很重要的话,这可能不够快。你需要一个实时解决方案来进行准确的碰撞检测,据我所知,vtk中没有碰撞检测功能。它是一个用于可视化的框架,你需要从头开始编写代码或者将现有的碰撞检测引擎与vtk配合使用。例如,Unity具有良好的实时碰撞检测功能,可以使用圆柱体作为基本形状。 - L.C.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接