Нахождение пересечения двух цилиндров в трехмерном пространстве с использованием VTK в Python - PullRequest
0 голосов
/ 04 марта 2019

Используя VTK в python, я написал некоторый код для создания актера для объектов, которые я хочу, например, для цилиндра:

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 Ответ

0 голосов
/ 06 марта 2019

Во-первых, вам нужно работать с объектом vtkPolyData (т.е. с геометрией), а не с vtkActor.Вам, вероятно, нужно будет использовать вывод vtkTransformPolyDataFilter в качестве vtkPolyData (как вы это делали в операторе else - пример here ), а не вызывать setUserMatrix.

Вы можете использовать vtkBooleanOperationPolyDataFilter : пример можно найти здесь (в C ++, но я уверен, что это может помочь) и здесь (в Python).Если получающаяся геометрия не пуста, то цилиндры пересекаются.

Если она не соответствует вашим потребностям, вы можете преобразовать цилиндры из полиданных в imagedata (объем изображения, вокселы), используя vtkImplicitModeller;тогда вычисление объема пересечения будет проще и точнее (вы можете использовать vtkImageLogic ).Вы также можете преобразовать пересечение обратно в vtkPolyData, используя vtkFlyingEdges3D (быстрая версия vtkMarchingCubes ).

Редактировать: как указано в комментариях, поскольку имеется много цилиндроввремя выполнения является вопросом.Вы можете попытаться оптимизировать процесс, вычислив расстояние между осями каждой пары цилиндров, чтобы определить, ЕСЛИ они пересекаются, и, если они это сделают, вычислить пересечение, как описано в первой части этого ответа.Моя идея заключается в следующем: вычислить кратчайшее расстояние между сегментами (один метод описан здесь , есть также код c ++ для расстояния между сегментами, это то, что вам нужно).Сравните расстояние с суммой радиуса двух цилиндров и, если оно короче, вычислите пересечение.

...