Example #1
0
    def openSurfaceAtPoint( self, polyData, seed ):
        '''
        Returns a new surface with an opening at the given seed.
        '''

        someradius = 1.0

        pointLocator = vtk.vtkPointLocator()
        pointLocator.SetDataSet( polyData )
        pointLocator.BuildLocator()

        # find the closest point next to the seed on the surface
        # id = pointLocator.FindClosestPoint(int(seed[0]),int(seed[1]),int(seed[2]))
        id = pointLocator.FindClosestPoint( seed )

        # the seed is now guaranteed on the surface
        seed = polyData.GetPoint( id )

        sphere = vtk.vtkSphere()
        sphere.SetCenter( seed[0], seed[1], seed[2] )
        sphere.SetRadius( someradius )

        clip = vtk.vtkClipPolyData()
        clip.SetInputData( polyData )
        clip.SetClipFunction( sphere )
        clip.Update()

        outPolyData = vtk.vtkPolyData()
        outPolyData.DeepCopy( clip.GetOutput() )

        return outPolyData
    def openSurfaceAtPoint(self, polyData, seed):
        '''
        Returns a new surface with an opening at the given seed.
        '''

        someradius = 1.0

        pointLocator = vtk.vtkPointLocator()
        pointLocator.SetDataSet(polyData)
        pointLocator.BuildLocator()

        # find the closest point next to the seed on the surface
        #id = pointLocator.FindClosestPoint(int(seed[0]),int(seed[1]),int(seed[2]))
        id = pointLocator.FindClosestPoint(seed)

        # the seed is now guaranteed on the surface
        seed = polyData.GetPoint(id)

        sphere = vtk.vtkSphere()
        sphere.SetCenter(seed[0], seed[1], seed[2])
        sphere.SetRadius(someradius)

        clip = vtk.vtkClipPolyData()
        clip.SetInput(polyData)
        clip.SetClipFunction(sphere)
        clip.Update()

        outPolyData = vtk.vtkPolyData()
        outPolyData.DeepCopy(clip.GetOutput())
        outPolyData.Update()

        return outPolyData
    def addModelPointLocator(self, name, polydata):

        if not name in self.pointLocatorDictionary:

            print "Adding point locator: {0}".format(name)
            pointLocator = vtk.vtkPointLocator()
            pointLocator.SetDataSet(polydata)
            pointLocator.AutomaticOn()
            pointLocator.BuildLocator()

            self.pointLocatorDictionary[name] = pointLocator
Example #4
0
    def addModelPointLocator(self, name, polydata):

        if not name in self.pointLocatorDictionary:

            print "Adding point locator: {0}".format(name)
            pointLocator = vtk.vtkPointLocator()
            pointLocator.SetDataSet(polydata)
            pointLocator.AutomaticOn()
            pointLocator.BuildLocator()

            self.pointLocatorDictionary[name] = pointLocator
Example #5
0
    def __init__(self):
        self.controlPointsMarkupNode = None
        self.curveModelNode = None

        self.tubeRadius = 5.0
        self.tubeResolution = 20

        self.numberOfIntermediatePoints = 20

        self.curvePoly = vtk.vtkPolyData()
        self.curvePoints = vtk.vtkPoints()
        self.curvePoly.SetPoints(self.curvePoints)

        self.curvePointsLocator = vtk.vtkPointLocator()
        self.curvePointsLocator.SetDataSet(self.curvePoly)

        self.interpolationMethod = InterpolationLinear
        self.pointInterpolationFunction = self.getInterpolatedPointsLinear

        self.closed = False
  def start( self, preview=False ):
    '''
    '''
    SlicerVmtk4CommonLib.Helper.Debug( "Starting Centerline Computation.." )

    # first we need the nodes
    currentModelNode = self.__inputModelNodeSelector.currentNode()
    currentSeedsNode = self.__seedFiducialsNodeSelector.currentNode()
    currentOutputModelNode = self.__outputModelNodeSelector.currentNode()
    currentVoronoiModelNode = self.__voronoiModelNodeSelector.currentNode()

    if not currentModelNode:
        # we need a input volume node
        return 0

    if not currentSeedsNode:
        # we need a seeds node
        return 0

    if not currentOutputModelNode or currentOutputModelNode.GetID() == currentModelNode.GetID():
        # we need a current model node, the display node is created later
        newModelNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelNode" )
        newModelNode.SetScene( slicer.mrmlScene )
        newModelNode.SetName( slicer.mrmlScene.GetUniqueNameByString( self.__outputModelNodeSelector.baseName ) )
        slicer.mrmlScene.AddNode( newModelNode )
        currentOutputModelNode = newModelNode

        self.__outputModelNodeSelector.setCurrentNode( currentOutputModelNode )

    if not currentVoronoiModelNode or currentVoronoiModelNode.GetID() == currentModelNode.GetID() or currentVoronoiModelNode.GetID() == currentOutputModelNode.GetID():
        # we need a current model node, the display node is created later
        newModelNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelNode" )
        newModelNode.SetScene( slicer.mrmlScene )
        newModelNode.SetName( slicer.mrmlScene.GetUniqueNameByString( self.__voronoiModelNodeSelector.baseName ) )
        slicer.mrmlScene.AddNode( newModelNode )
        currentVoronoiModelNode = newModelNode

        self.__voronoiModelNodeSelector.setCurrentNode( currentVoronoiModelNode )

    # the output models
    preparedModel = vtk.vtkPolyData()
    model = vtk.vtkPolyData()
    network = vtk.vtkPolyData()
    voronoi = vtk.vtkPolyData()

    currentCoordinatesRAS = [0, 0, 0]

    # grab the current coordinates
    currentSeedsNode.GetFiducialCoordinates( currentCoordinatesRAS )

    # prepare the model
    preparedModel.DeepCopy( self.GetLogic().prepareModel( currentModelNode.GetPolyData() ) )
    preparedModel.Update()

    # decimate the model (only for network extraction)
    model.DeepCopy( self.GetLogic().decimateSurface( preparedModel ) )
    model.Update()

    # open the model at the seed (only for network extraction)
    model.DeepCopy( self.GetLogic().openSurfaceAtPoint( model, currentCoordinatesRAS ) )
    model.Update()

    # extract Network
    network.DeepCopy( self.GetLogic().extractNetwork( model ) )
    network.Update()

    #
    #
    # not preview mode: real computation!
    if not preview:
        # here we start the actual centerline computation which is mathematically more robust and accurate but takes longer than the network extraction

        # clip surface at endpoints identified by the network extraction
        tupel = self.GetLogic().clipSurfaceAtEndPoints( network, currentModelNode.GetPolyData() )
        clippedSurface = tupel[0]
        endpoints = tupel[1]

        # now find the one endpoint which is closest to the seed and use it as the source point for centerline computation
        # all other endpoints are the target points
        sourcePoint = [0, 0, 0]

        # the following arrays have the same indexes and are synchronized at all times
        distancesToSeed = []
        targetPoints = []

        # we now need to loop through the endpoints two times

        # first loop is to detect the endpoint resulting in the tiny hole we poked in the surface
        # this is very close to our seed but not the correct sourcePoint
        for i in range( endpoints.GetNumberOfPoints() ):

            currentPoint = endpoints.GetPoint( i )
            # get the euclidean distance
            currentDistanceToSeed = math.sqrt( math.pow( ( currentPoint[0] - currentCoordinatesRAS[0] ), 2 ) +
                                               math.pow( ( currentPoint[1] - currentCoordinatesRAS[1] ), 2 ) +
                                               math.pow( ( currentPoint[2] - currentCoordinatesRAS[2] ), 2 ) )

            targetPoints.append( currentPoint )
            distancesToSeed.append( currentDistanceToSeed )

        # now we have a list of distances with the corresponding points
        # the index with the most minimal distance is the holePoint, we want to ignore it
        # the index with the second minimal distance is the point closest to the seed, we want to set it as sourcepoint
        # all other points are the targetpoints

        # get the index of the holePoint, which we want to remove from our endPoints
        holePointIndex = distancesToSeed.index( min( distancesToSeed ) )
        # .. and remove it
        distancesToSeed.pop( holePointIndex )
        targetPoints.pop( holePointIndex )

        # now find the sourcepoint
        sourcePointIndex = distancesToSeed.index( min( distancesToSeed ) )
        # .. and remove it after saving it as the sourcePoint
        sourcePoint = targetPoints[sourcePointIndex]
        distancesToSeed.pop( sourcePointIndex )
        targetPoints.pop( sourcePointIndex )

        # again, at this point we have a) the sourcePoint and b) a list of real targetPoints


        # now create the sourceIdList and targetIdList for the actual centerline computation
        sourceIdList = vtk.vtkIdList()
        targetIdList = vtk.vtkIdList()

        pointLocator = vtk.vtkPointLocator()
        pointLocator.SetDataSet( preparedModel )
        pointLocator.BuildLocator()

        # locate the source on the surface
        sourceId = pointLocator.FindClosestPoint( sourcePoint )
        sourceIdList.InsertNextId( sourceId )

        f = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLAnnotationFiducialNode" )
        f.SetFiducialCoordinates( sourcePoint )
        f.Initialize( slicer.mrmlScene )
        f.SelectedOn()

        # locate the endpoints on the surface
        for p in targetPoints:

                f = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLAnnotationFiducialNode" )
                f.SetFiducialCoordinates( p )
                f.Initialize( slicer.mrmlScene )

                id = pointLocator.FindClosestPoint( p )
                targetIdList.InsertNextId( id )


        tupel = self.GetLogic().computeCenterlines( preparedModel, sourceIdList, targetIdList )
        network.DeepCopy( tupel[0] )
        voronoi.DeepCopy( tupel[1] )

    #
    #
    # update the display of the original model in terms of opacity
    currentModelDisplayNode = currentModelNode.GetDisplayNode()

    if not currentModelDisplayNode:

        # create new displayNode
        currentModelDisplayNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelDisplayNode" )
        slicer.mrmlScene.AddNode( currentModelDisplayNode )

    currentModelDisplayNode.SetOpacity( 0.4 )
    currentModelDisplayNode.Modified()
    currentModelDisplayNode.SetModifiedSinceRead( 1 )

    # update the reference between model node and it's display node
    currentModelNode.SetAndObserveDisplayNodeID( currentModelDisplayNode.GetID() )
    currentModelNode.Modified()
    currentModelNode.SetModifiedSinceRead( 1 )

    #
    # finally:
    # propagate output model to nodes
    currentOutputModelNode.SetAndObservePolyData( network )
    currentOutputModelNode.Modified()
    currentOutputModelNode.SetModifiedSinceRead( 1 )

    currentOutputModelDisplayNode = currentOutputModelNode.GetDisplayNode()

    if not currentOutputModelDisplayNode:

        # create new displayNode
        currentOutputModelDisplayNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelDisplayNode" )
        slicer.mrmlScene.AddNode( currentOutputModelDisplayNode )

    # always configure the displayNode to show the model
    currentOutputModelDisplayNode.SetPolyData( currentOutputModelNode.GetPolyData() )
    currentOutputModelDisplayNode.SetColor( 0.0, 0.0, 0.4 ) # red
    currentOutputModelDisplayNode.SetBackfaceCulling( 0 )
    currentOutputModelDisplayNode.SetSliceIntersectionVisibility( 0 )
    currentOutputModelDisplayNode.SetVisibility( 1 )
    currentOutputModelDisplayNode.SetOpacity( 1.0 )
    currentOutputModelDisplayNode.Modified()
    currentOutputModelDisplayNode.SetModifiedSinceRead( 1 )

    # update the reference between model node and it's display node
    currentOutputModelNode.SetAndObserveDisplayNodeID( currentOutputModelDisplayNode.GetID() )
    currentOutputModelNode.Modified()
    currentOutputModelNode.SetModifiedSinceRead( 1 )

    # only update the voronoi node if we are not in preview mode

    if not preview:
        currentVoronoiModelNode.SetAndObservePolyData( voronoi )
        currentVoronoiModelNode.Modified()
        currentVoronoiModelNode.SetModifiedSinceRead( 1 )

        currentVoronoiModelDisplayNode = currentVoronoiModelNode.GetDisplayNode()

        if not currentVoronoiModelDisplayNode:

            # create new displayNode
            currentVoronoiModelDisplayNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelDisplayNode" )
            slicer.mrmlScene.AddNode( currentVoronoiModelDisplayNode )

        # always configure the displayNode to show the model
        currentVoronoiModelDisplayNode.SetPolyData( currentVoronoiModelNode.GetPolyData() )
        currentVoronoiModelDisplayNode.SetScalarVisibility( 1 )
        currentVoronoiModelDisplayNode.SetBackfaceCulling( 0 )
        currentVoronoiModelDisplayNode.SetActiveScalarName( "Radius" )
        currentVoronoiModelDisplayNode.SetAndObserveColorNodeID( slicer.mrmlScene.GetNodesByName( "Labels" ).GetItemAsObject( 0 ).GetID() )
        currentVoronoiModelDisplayNode.SetSliceIntersectionVisibility( 0 )
        currentVoronoiModelDisplayNode.SetVisibility( 1 )
        currentVoronoiModelDisplayNode.SetOpacity( 0.5 )
        currentVoronoiModelDisplayNode.Modified()
        currentVoronoiModelDisplayNode.SetModifiedSinceRead( 1 )

        # update the reference between model node and it's display node
        currentVoronoiModelNode.SetAndObserveDisplayNodeID( currentVoronoiModelDisplayNode.GetID() )
        currentVoronoiModelNode.Modified()
        currentVoronoiModelNode.SetModifiedSinceRead( 1 )



    SlicerVmtk4CommonLib.Helper.Debug( "End of Centerline Computation.." )
    def start(self, preview=False):
        '''
    '''
        SlicerVmtk4CommonLib.Helper.Debug("Starting Centerline Computation..")

        # first we need the nodes
        currentModelNode = self.__inputModelNodeSelector.currentNode()
        currentSeedsNode = self.__seedFiducialsNodeSelector.currentNode()
        currentOutputModelNode = self.__outputModelNodeSelector.currentNode()
        currentVoronoiModelNode = self.__voronoiModelNodeSelector.currentNode()

        if not currentModelNode:
            # we need a input volume node
            return 0

        if not currentSeedsNode:
            # we need a seeds node
            return 0

        if not currentOutputModelNode or currentOutputModelNode.GetID(
        ) == currentModelNode.GetID():
            # we need a current model node, the display node is created later
            newModelNode = slicer.mrmlScene.CreateNodeByClass(
                "vtkMRMLModelNode")
            newModelNode.SetScene(slicer.mrmlScene)
            newModelNode.SetName(
                slicer.mrmlScene.GetUniqueNameByString(
                    self.__outputModelNodeSelector.baseName))
            slicer.mrmlScene.AddNode(newModelNode)
            currentOutputModelNode = newModelNode

            self.__outputModelNodeSelector.setCurrentNode(
                currentOutputModelNode)

        if not currentVoronoiModelNode or currentVoronoiModelNode.GetID(
        ) == currentModelNode.GetID() or currentVoronoiModelNode.GetID(
        ) == currentOutputModelNode.GetID():
            # we need a current model node, the display node is created later
            newModelNode = slicer.mrmlScene.CreateNodeByClass(
                "vtkMRMLModelNode")
            newModelNode.SetScene(slicer.mrmlScene)
            newModelNode.SetName(
                slicer.mrmlScene.GetUniqueNameByString(
                    self.__voronoiModelNodeSelector.baseName))
            slicer.mrmlScene.AddNode(newModelNode)
            currentVoronoiModelNode = newModelNode

            self.__voronoiModelNodeSelector.setCurrentNode(
                currentVoronoiModelNode)

        # the output models
        preparedModel = vtk.vtkPolyData()
        model = vtk.vtkPolyData()
        network = vtk.vtkPolyData()
        voronoi = vtk.vtkPolyData()

        currentCoordinatesRAS = [0, 0, 0]

        # grab the current coordinates
        currentSeedsNode.GetFiducialCoordinates(currentCoordinatesRAS)

        # prepare the model
        preparedModel.DeepCopy(self.GetLogic().prepareModel(
            currentModelNode.GetPolyData()))
        preparedModel.Update()

        # decimate the model (only for network extraction)
        model.DeepCopy(self.GetLogic().decimateSurface(preparedModel))
        model.Update()

        # open the model at the seed (only for network extraction)
        model.DeepCopy(self.GetLogic().openSurfaceAtPoint(
            model, currentCoordinatesRAS))
        model.Update()

        # extract Network
        network.DeepCopy(self.GetLogic().extractNetwork(model))
        network.Update()

        #
        #
        # not preview mode: real computation!
        if not preview:
            # here we start the actual centerline computation which is mathematically more robust and accurate but takes longer than the network extraction

            # clip surface at endpoints identified by the network extraction
            tupel = self.GetLogic().clipSurfaceAtEndPoints(
                network, currentModelNode.GetPolyData())
            clippedSurface = tupel[0]
            endpoints = tupel[1]

            # now find the one endpoint which is closest to the seed and use it as the source point for centerline computation
            # all other endpoints are the target points
            sourcePoint = [0, 0, 0]

            # the following arrays have the same indexes and are synchronized at all times
            distancesToSeed = []
            targetPoints = []

            # we now need to loop through the endpoints two times

            # first loop is to detect the endpoint resulting in the tiny hole we poked in the surface
            # this is very close to our seed but not the correct sourcePoint
            for i in range(endpoints.GetNumberOfPoints()):

                currentPoint = endpoints.GetPoint(i)
                # get the euclidean distance
                currentDistanceToSeed = math.sqrt(
                    math.pow((currentPoint[0] - currentCoordinatesRAS[0]), 2) +
                    math.pow((currentPoint[1] - currentCoordinatesRAS[1]), 2) +
                    math.pow((currentPoint[2] - currentCoordinatesRAS[2]), 2))

                targetPoints.append(currentPoint)
                distancesToSeed.append(currentDistanceToSeed)

            # now we have a list of distances with the corresponding points
            # the index with the most minimal distance is the holePoint, we want to ignore it
            # the index with the second minimal distance is the point closest to the seed, we want to set it as sourcepoint
            # all other points are the targetpoints

            # get the index of the holePoint, which we want to remove from our endPoints
            holePointIndex = distancesToSeed.index(min(distancesToSeed))
            # .. and remove it
            distancesToSeed.pop(holePointIndex)
            targetPoints.pop(holePointIndex)

            # now find the sourcepoint
            sourcePointIndex = distancesToSeed.index(min(distancesToSeed))
            # .. and remove it after saving it as the sourcePoint
            sourcePoint = targetPoints[sourcePointIndex]
            distancesToSeed.pop(sourcePointIndex)
            targetPoints.pop(sourcePointIndex)

            # again, at this point we have a) the sourcePoint and b) a list of real targetPoints

            # now create the sourceIdList and targetIdList for the actual centerline computation
            sourceIdList = vtk.vtkIdList()
            targetIdList = vtk.vtkIdList()

            pointLocator = vtk.vtkPointLocator()
            pointLocator.SetDataSet(preparedModel)
            pointLocator.BuildLocator()

            # locate the source on the surface
            sourceId = pointLocator.FindClosestPoint(sourcePoint)
            sourceIdList.InsertNextId(sourceId)

            f = slicer.mrmlScene.CreateNodeByClass(
                "vtkMRMLAnnotationFiducialNode")
            f.SetFiducialCoordinates(sourcePoint)
            f.Initialize(slicer.mrmlScene)
            f.SelectedOn()

            # locate the endpoints on the surface
            for p in targetPoints:

                f = slicer.mrmlScene.CreateNodeByClass(
                    "vtkMRMLAnnotationFiducialNode")
                f.SetFiducialCoordinates(p)
                f.Initialize(slicer.mrmlScene)

                id = pointLocator.FindClosestPoint(p)
                targetIdList.InsertNextId(id)

            tupel = self.GetLogic().computeCenterlines(preparedModel,
                                                       sourceIdList,
                                                       targetIdList)
            network.DeepCopy(tupel[0])
            voronoi.DeepCopy(tupel[1])

        #
        #
        # update the display of the original model in terms of opacity
        currentModelDisplayNode = currentModelNode.GetDisplayNode()

        if not currentModelDisplayNode:

            # create new displayNode
            currentModelDisplayNode = slicer.mrmlScene.CreateNodeByClass(
                "vtkMRMLModelDisplayNode")
            slicer.mrmlScene.AddNode(currentModelDisplayNode)

        currentModelDisplayNode.SetOpacity(0.4)
        currentModelDisplayNode.Modified()
        currentModelDisplayNode.SetModifiedSinceRead(1)

        # update the reference between model node and it's display node
        currentModelNode.SetAndObserveDisplayNodeID(
            currentModelDisplayNode.GetID())
        currentModelNode.Modified()
        currentModelNode.SetModifiedSinceRead(1)

        #
        # finally:
        # propagate output model to nodes
        currentOutputModelNode.SetAndObservePolyData(network)
        currentOutputModelNode.Modified()
        currentOutputModelNode.SetModifiedSinceRead(1)

        currentOutputModelDisplayNode = currentOutputModelNode.GetDisplayNode()

        if not currentOutputModelDisplayNode:

            # create new displayNode
            currentOutputModelDisplayNode = slicer.mrmlScene.CreateNodeByClass(
                "vtkMRMLModelDisplayNode")
            slicer.mrmlScene.AddNode(currentOutputModelDisplayNode)

        # always configure the displayNode to show the model
        currentOutputModelDisplayNode.SetPolyData(
            currentOutputModelNode.GetPolyData())
        currentOutputModelDisplayNode.SetColor(0.0, 0.0, 0.4)  # red
        currentOutputModelDisplayNode.SetBackfaceCulling(0)
        currentOutputModelDisplayNode.SetSliceIntersectionVisibility(0)
        currentOutputModelDisplayNode.SetVisibility(1)
        currentOutputModelDisplayNode.SetOpacity(1.0)
        currentOutputModelDisplayNode.Modified()
        currentOutputModelDisplayNode.SetModifiedSinceRead(1)

        # update the reference between model node and it's display node
        currentOutputModelNode.SetAndObserveDisplayNodeID(
            currentOutputModelDisplayNode.GetID())
        currentOutputModelNode.Modified()
        currentOutputModelNode.SetModifiedSinceRead(1)

        # only update the voronoi node if we are not in preview mode

        if not preview:
            currentVoronoiModelNode.SetAndObservePolyData(voronoi)
            currentVoronoiModelNode.Modified()
            currentVoronoiModelNode.SetModifiedSinceRead(1)

            currentVoronoiModelDisplayNode = currentVoronoiModelNode.GetDisplayNode(
            )

            if not currentVoronoiModelDisplayNode:

                # create new displayNode
                currentVoronoiModelDisplayNode = slicer.mrmlScene.CreateNodeByClass(
                    "vtkMRMLModelDisplayNode")
                slicer.mrmlScene.AddNode(currentVoronoiModelDisplayNode)

            # always configure the displayNode to show the model
            currentVoronoiModelDisplayNode.SetPolyData(
                currentVoronoiModelNode.GetPolyData())
            currentVoronoiModelDisplayNode.SetScalarVisibility(1)
            currentVoronoiModelDisplayNode.SetBackfaceCulling(0)
            currentVoronoiModelDisplayNode.SetActiveScalarName("Radius")
            currentVoronoiModelDisplayNode.SetAndObserveColorNodeID(
                slicer.mrmlScene.GetNodesByName("Labels").GetItemAsObject(
                    0).GetID())
            currentVoronoiModelDisplayNode.SetSliceIntersectionVisibility(0)
            currentVoronoiModelDisplayNode.SetVisibility(1)
            currentVoronoiModelDisplayNode.SetOpacity(0.5)
            currentVoronoiModelDisplayNode.Modified()
            currentVoronoiModelDisplayNode.SetModifiedSinceRead(1)

            # update the reference between model node and it's display node
            currentVoronoiModelNode.SetAndObserveDisplayNodeID(
                currentVoronoiModelDisplayNode.GetID())
            currentVoronoiModelNode.Modified()
            currentVoronoiModelNode.SetModifiedSinceRead(1)

        SlicerVmtk4CommonLib.Helper.Debug("End of Centerline Computation..")