Collision Detection

Here is a follow-up on the topic of collision detection as suggested by @mau_igna_06 on this post.

Following @manjula example, I was able to integrate the vtk.collisionDetectionFilter() into my code;

def findMeshCollision( inputNodeNames, visibility=True, verbose=False ):
    '''
        Find Mesh Collision
            This function finds a collision or intersection between two surface meshesu=fluvio_lobo
    '''

    # Variables
    if isinstance( inputNodeNames, str ):
        inputNodeNames      = [ inputNodeNames ]
    numberOfNodes           = len( inputNodeNames )
    #collisionDetection      = vtkSRCP.vtkCollisionDetectionFilter()
    collisionDetection      = vtk.vtkCollisionDetectionFilter()
    numberOfCollisions      = 0
    collisionFlag           = False
    inputNodes              = []
    
    for i in range( 0, numberOfNodes ):
        inputNode           = slicer.util.getNode( inputNodeNames[i] )
        inputNodes.append( inputNode )

    # Collision Detection
    for i in range( 0, numberOfNodes-1 ):
        collisionDetection.SetInputData( 0, inputNodes[i].GetPolyData() )
        collisionDetection.SetInputData( 1, inputNodes[i+1].GetPolyData() )
        matrix              = vtk.vtkMatrix4x4()
        collisionDetection.SetMatrix( 0, matrix )
        collisionDetection.SetMatrix( 1, matrix )
        collisionDetection.SetBoxTolerance( 0.0 )
        collisionDetection.SetCellTolerance( 0.0 )
        collisionDetection.SetNumberOfCellsPerNode( 2 )
        collisionDetection.Update()
    
    numberOfCollisions      = collisionDetection.GetNumberOfContacts()
    if numberOfCollisions > 0:
        collisionFlag       = True
    else:
        collisionFlag       = False
    
    # Status Verbose
    if(verbose):
        if(collisionFlag == True ):
            print( "{} Collisions Detected".format( numberOfCollisions ) )
        else:
            print( "No Collisions Detected" )

    # Return;
    return collisionFlag, numberOfCollisions

I had to use the vtk.collisionDetectionFilter() function call, vtkSlicerRtCommonPython.vtkCollisionDetectionFilter() kept giving the missing attribute error:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "D:\Gits\DASH\cmf\_functions.py", line 365, in findMeshCollision
    collisionDetection      = vtkSRCP.vtkCollisionDetectionFilter()
AttributeError: module 'vtkSlicerRtCommonPython' has no attribute 'vtkCollisionDetectionFilter'

Either way, the function seems work thus far…

No Collisions Detected
(False, 0)

56 Collisions Detected
(True, 56)
2 Likes

vtkSlicerRtCommonPython.vtkCollisionDetectionFilter() kept giving the missing attribute error

This happens because you need to install SlicerRT extension to use that class. But vtk.vtkCollisionDetectionFilter() class was added to Slicer core in recent Slicer Preview releases (it is the same filter)

2 Likes

We had to remove vtkCollisionDetectionFilter from SlicerRT as it was not necessary anymore and it interfered with the one that is in VTK.

We had to remove vtkCollisionDetectionFilter from SlicerRT as it was not necessary anymore and it interfered with the one that is in VTK.

Does SlicerRT on the Slicer Stable release have this filter? BoneReconstructionPlanner uses this filter and currently only works on Slicer Stable Release.
Some functions BRP used changed name on preview release. Maybe I can have two different branches, one for each release type, if the answer to the question above is yes

Slicer Stable Release (Slicer-4.11.20210226) uses VTK-8.2, which does not contain vtkCollisionDetectionFilter, so there SlicerRT provides it.

Usually we try to keep the same extension source code to work with the latest Slicer Stable Release and Slicer Preview Release and manage small API differences using if/else or try/except blocks. If this gets too complicated (e.g., in case of vtkCollisionDetectionFilter we should have moved the filter into a separate library to prevent the header files from clashing, which would have been too much work) then we create a separate branch, which usually means that the stable branch does not get any more updates (because we don’t have time to backport and test all changes).

1 Like

Just wanted to jump into this thread, I implemented the code that Fluvio discussed above, and it seems to be working only when the transforms are hardened and won’t use geometry location if it is observing a transform node. Is there any way to make the vtkCollisionDetectionFilter observe a transform node?

I would modify the function like this:

def findMeshCollision( node1, node2, verbose=False ):
    '''
        Find Mesh Collision
            This function finds a collision or intersection between two surface meshesu=fluvio_lobo
    '''
    #
    # Variables
    #collisionDetection      = vtkSRCP.vtkCollisionDetectionFilter()
    collisionDetection      = vtk.vtkCollisionDetectionFilter()
    numberOfCollisions      = 0
    collisionFlag           = False
    #
    # Collision Detection
    node1ToWorldTransformMatrix = vtk.vtkMatrix4x4()
    node2ToWorldTransformMatrix = vtk.vtkMatrix4x4()
    node1ParentTransformNode = node1.GetParentTransformNode()
    node2ParentTransformNode = node2.GetParentTransformNode()
    if node1ParentTransformNode != None:
        node1ParentTransformNode.GetMatrixTransformToWorld(node1ToWorldTransformMatrix)
    if node2ParentTransformNode != None:
        node2ParentTransformNode.GetMatrixTransformToWorld(node2ToWorldTransformMatrix)
    #
    collisionDetection.SetInputData( 0, node1.GetPolyData() )
    collisionDetection.SetInputData( 1, node2.GetPolyData() )
    collisionDetection.SetMatrix( 0, node1ToWorldTransformMatrix )
    collisionDetection.SetMatrix( 1, node2ToWorldTransformMatrix )
    collisionDetection.SetBoxTolerance( 0.0 )
    collisionDetection.SetCellTolerance( 0.0 )
    collisionDetection.SetNumberOfCellsPerNode( 2 )
    collisionDetection.Update()
    #
    numberOfCollisions      = collisionDetection.GetNumberOfContacts()
    if numberOfCollisions > 0:
        collisionFlag       = True
    else:
        collisionFlag       = False
    #
    # Status Verbose
    if(verbose):
        if(collisionFlag == True ):
            print( "{} Collisions Detected".format( numberOfCollisions ) )
        else:
            print( "No Collisions Detected" )
    #
    # Return;
    return collisionFlag, numberOfCollisions

Hope it helps

4 Likes