简体   繁体   English

在python中使用VTK在3D空间中找到两个圆柱体的交集

[英]Finding the intersection of two cylinders in 3D space using VTK in python

Using VTK in python i wrote some code to create an actor for objects that i want, eg for cylinder:在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

This function returns an actor where i can render it later using vtkRender .这个函数返回一个actor,我可以稍后使用vtkRender渲染它。 Now what i want is to first find whether two given cylinder Actors are intersected or not and second find the intersection points.现在我想要的是首先找到两个给定的圆柱体Actors是否相交,然后找到相交点。 Could i use the vtkTriangleFilter on my cylinder and use the vtkOBBTree and ray casting to find whether the intersection happens or not?我能使用vtkTriangleFilter我的缸和使用vtkOBBTree和光线投射找到交集是否发生?

Here are two oriented cylinders that are intersected:这是相交的两个定向圆柱体: 相交圆柱

First, you'll need to work on the vtkPolyData object (ie the geometry), not on the vtkActor.首先,您需要处理 vtkPolyData 对象(即几何体),而不是 vtkActor。 You'll probably need to use vtkTransformPolyDataFilter output as your vtkPolyData (as you did in the else statement - example here ) rather than calling setUserMatrix.您可能需要使用 vtkTransformPolyDataFilter 输出作为您的 vtkPolyData(就像您在 else 语句中所做的一样 -此处的示例)而不是调用 setUserMatrix。

You can use vtkBooleanOperationPolyDataFilter : an example can be found here (in C++, but I'm sure it can help) and here (in Python).您可以使用vtkBooleanOperationPolyDataFilter :可以在此处(在 C++ 中,但我确定它可以提供帮助)和此处(在 Python 中)找到一个示例。 If the resulting geometry is not empty, then the cylinders intersect.如果生成的几何图形不为空,则圆柱体相交。

If it does not fit your needs, you can convert the cylinders from polydata to imagedata (image volume, voxels) using vtkImplicitModeller;如果它不符合您的需求,您可以使用 vtkImplicitModeller 将圆柱体从多边形数据转换为图像数据(图像体积、体素); then computing the intersection volume is easier and more accurate (you can use vtkImageLogic ).然后计算相交体积更容易和更准确(您可以使用vtkImageLogic )。 You can also convert the intersection back to vtkPolyData using vtkFlyingEdges3D (a fast version of vtkMarchingCubes ).您还可以使用vtkFlyingEdges3DvtkMarchingCubes的快速版本)将交集转换回vtkPolyData

Edit: as disussed in the comments, because there are many cylinders execution time is a matter.编辑:正如评论中所讨论的那样,因为有很多圆柱体执行时间是一个问题。 You could try to optimize the process by computing the distance between the axis of each pair of cylinders to detect IF they intersect and in case they do, compute the intersection as described in the first part of this answer.您可以尝试通过计算每对圆柱体的轴之间的距离来优化该过程,以检测它们是否相交,如果它们相交,请按照本答案第一部分中的描述计算相交。 My idea is the following: compute the shortest distance between the segments (one method is described here , there's also the c++ code for segment-to-segment distance, that's what you need).我的想法如下:计算段之间的最短距离(这里描述一种方法,还有段到段距离的 c++ 代码,这就是你需要的)。 Compare the distance with the sum of the radius of the two cylinders and if it's shorter, compute the intersection.将距离与两个圆柱体的半径之和进行比较,如果较短,则计算交点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM