def generateResectionVolume(self, fiducialNode, modelNode): if (fiducialNode != None): self.FiducialNode = fiducialNode self.PolyData = vtk.vtkPolyData() self.updatePoints() self.Delaunay = vtk.vtkDelaunay3D() if (vtk.VTK_MAJOR_VERSION <= 5): self.Delaunay.SetInput(self.PolyData) else: self.Delaunay.SetInputData(self.PolyData) self.Delaunay.Update() self.SurfaceFilter = vtk.vtkDataSetSurfaceFilter() self.SurfaceFilter.SetInputConnection( self.Delaunay.GetOutputPort()) self.SurfaceFilter.Update() self.Smoother = vtk.vtkButterflySubdivisionFilter() self.Smoother.SetInputConnection( self.SurfaceFilter.GetOutputPort()) self.Smoother.SetNumberOfSubdivisions(3) self.Smoother.Update() if modelNode.GetDisplayNodeID() == None: modelDisplayNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelDisplayNode") modelDisplayNode.SetColor(0, 0, 1) # Blue modelDisplayNode.BackfaceCullingOff() modelDisplayNode.SetOpacity(0.3) # Between 0-1, 1 being opaque slicer.mrmlScene.AddNode(modelDisplayNode) modelNode.SetAndObserveDisplayNodeID(modelDisplayNode.GetID()) if (vtk.VTK_MAJOR_VERSION <= 5): modelNode.SetAndObservePolyData(self.Smoother.GetOutput()) else: modelNode.SetPolyDataConnection(self.Smoother.GetOutputPort()) modelNode.Modified() self.tag = self.FiducialNode.AddObserver( 'ModifiedEvent', self.updateResectionVolume)
def generateResectionVolume(self, fiducialNode, modelNode): if (fiducialNode != None): self.FiducialNode = fiducialNode self.PolyData = vtk.vtkPolyData() self.updatePoints() self.Delaunay = vtk.vtkDelaunay3D() if (vtk.VTK_MAJOR_VERSION <= 5): self.Delaunay.SetInput(self.PolyData) else: self.Delaunay.SetInputData(self.PolyData) self.Delaunay.Update() self.SurfaceFilter = vtk.vtkDataSetSurfaceFilter() self.SurfaceFilter.SetInputConnection(self.Delaunay.GetOutputPort()) self.SurfaceFilter.Update() self.Smoother = vtk.vtkButterflySubdivisionFilter() self.Smoother.SetInputConnection(self.SurfaceFilter.GetOutputPort()) self.Smoother.SetNumberOfSubdivisions(3) self.Smoother.Update() if modelNode.GetDisplayNodeID() == None: modelDisplayNode = slicer.mrmlScene.CreateNodeByClass("vtkMRMLModelDisplayNode") modelDisplayNode.SetColor(0,0,1) # Blue modelDisplayNode.BackfaceCullingOff() modelDisplayNode.SetOpacity(0.3) # Between 0-1, 1 being opaque slicer.mrmlScene.AddNode(modelDisplayNode) modelNode.SetAndObserveDisplayNodeID(modelDisplayNode.GetID()) if (vtk.VTK_MAJOR_VERSION <= 5): modelNode.SetAndObservePolyData(self.Smoother.GetOutput()) else: modelNode.SetPolyDataConnection(self.Smoother.GetOutputPort()) modelNode.Modified() self.tag = self.FiducialNode.AddObserver('ModifiedEvent', self.updateResectionVolume)
def run(self, inputModel, sModel, seedList): """ Run the actual algorithm """ self.delayDisplay('Running the aglorithm') tri = vtk.vtkDelaunay3D() tri.SetInputData(sModel.GetPolyData()) elev = vtk.vtkElevationFilter() elev.SetInputConnection(tri.GetOutput()) implicitDataSet = vtk.vtkImplicitDataSet() implicitDataSet.SetDataSet(elev.GetOutput()) triangle = vtk.vtkTriangleFilter() triangle.SetInputData(inputModel.GetPolyData()) triangle.Update() computeNormals = vtk.vtkPolyDataNormals() computeNormals.SetInputData(triangle.GetOutput()) computeNormals.ComputeCellNormalsOn() computeNormals.Update() clip = vtk.vtkClipPolyData() clip.SetInputData(computeNormals.GetOutput()) clip.SetClipFunction(implicitDataSet) clip.InsideOutOff() clip.Update() clean = vtk.vtkCleanPolyData() clean.SetInputData(clip.GetOutput()) clean.Update() polydata = clean.GetOutput() cellData = polydata.GetCellData() normals = cellData.GetNormals() meanNormal = [0, 0, 0] nOfTuples = normals.GetNumberOfTuples() for cellIndex in range(0, nOfTuples): cellNormal = [0, 0, 0] cell = polydata.GetCell(cellIndex) normals.GetTuple(cellIndex, cellNormal) meanNormal[0] = meanNormal[0] + cellNormal[0] meanNormal[1] = meanNormal[1] + cellNormal[1] meanNormal[2] = meanNormal[2] + cellNormal[2] meanNormal[0] = meanNormal[0] / nOfTuples meanNormal[1] = meanNormal[1] / nOfTuples meanNormal[2] = meanNormal[2] / nOfTuples print("Normal: " + str(meanNormal)) seed1 = [0, 0, 0] seedList.GetNthFiducialPosition(0, seed1) vector = [ seed1[0] + 50 * meanNormal[0], seed1[1] + 50 * meanNormal[1], seed1[2] + 50 * meanNormal[2] ] seedList.AddFiducialFromArray(vector) # Calculate perpendicular vectors v1 = [0, 0, 0] v2 = [0, 0, 0] math = vtk.vtkMath() math.Perpendiculars(meanNormal, v2, v1, 0) # Normalize vectors math.Normalize(meanNormal) math.Normalize(v1) math.Normalize(v2) # create matrix4x4 transform = slicer.mrmlScene.CreateNodeByClass( 'vtkMRMLLinearTransformNode') slicer.mrmlScene.AddNode(transform) matrix = transform.GetMatrixTransformToParent() matrix.SetElement(0, 0, v1[0]) matrix.SetElement(1, 0, v1[1]) matrix.SetElement(2, 0, v1[2]) matrix.SetElement(3, 0, 0.0) matrix.SetElement(0, 1, meanNormal[0]) matrix.SetElement(1, 1, meanNormal[1]) matrix.SetElement(2, 1, meanNormal[2]) matrix.SetElement(3, 1, 0.0) matrix.SetElement(0, 2, v2[0]) matrix.SetElement(1, 2, v2[1]) matrix.SetElement(2, 2, v2[2]) matrix.SetElement(3, 2, 0.0) matrix.SetElement(0, 3, seed1[0]) matrix.SetElement(1, 3, seed1[1]) matrix.SetElement(2, 3, seed1[2]) matrix.SetElement(3, 3, 1.0) return True
def run(self,inputModel,sModel,seedList): """ Run the actual algorithm """ self.delayDisplay('Running the aglorithm') tri = vtk.vtkDelaunay3D() tri.SetInputData(sModel.GetPolyData()) elev = vtk.vtkElevationFilter() elev.SetInputConnection(tri.GetOutput()) implicitDataSet = vtk.vtkImplicitDataSet() implicitDataSet.SetDataSet(elev.GetOutput()) triangle = vtk.vtkTriangleFilter() triangle.SetInputData(inputModel.GetPolyData()) triangle.Update() computeNormals = vtk.vtkPolyDataNormals() computeNormals.SetInputData(triangle.GetOutput()) computeNormals.ComputeCellNormalsOn() computeNormals.Update() clip = vtk.vtkClipPolyData() clip.SetInputData(computeNormals.GetOutput()) clip.SetClipFunction(implicitDataSet) clip.InsideOutOff() clip.Update() clean = vtk.vtkCleanPolyData() clean.SetInputData(clip.GetOutput()) clean.Update() polydata = clean.GetOutput() cellData = polydata.GetCellData() normals = cellData.GetNormals() meanNormal = [0,0,0] nOfTuples = normals.GetNumberOfTuples() for cellIndex in range(0, nOfTuples): cellNormal = [0,0,0] cell = polydata.GetCell(cellIndex) normals.GetTuple(cellIndex, cellNormal) meanNormal[0] = meanNormal[0] + cellNormal[0] meanNormal[1] = meanNormal[1] + cellNormal[1] meanNormal[2] = meanNormal[2] + cellNormal[2] meanNormal[0] = meanNormal[0] / nOfTuples meanNormal[1] = meanNormal[1] / nOfTuples meanNormal[2] = meanNormal[2] / nOfTuples print("Normal: " + str(meanNormal)) seed1 = [0,0,0] seedList.GetNthFiducialPosition(0,seed1) vector = [seed1[0]+50*meanNormal[0], seed1[1]+50*meanNormal[1], seed1[2]+50*meanNormal[2]] seedList.AddFiducialFromArray(vector) # Calculate perpendicular vectors v1 = [0,0,0] v2 = [0,0,0] math = vtk.vtkMath() math.Perpendiculars(meanNormal, v2, v1, 0) # Normalize vectors math.Normalize(meanNormal) math.Normalize(v1) math.Normalize(v2) # create matrix4x4 transform = slicer.mrmlScene.CreateNodeByClass('vtkMRMLLinearTransformNode') slicer.mrmlScene.AddNode(transform) matrix = transform.GetMatrixTransformToParent() matrix.SetElement(0,0,v1[0]) matrix.SetElement(1,0,v1[1]) matrix.SetElement(2,0,v1[2]) matrix.SetElement(3,0,0.0) matrix.SetElement(0,1,meanNormal[0]) matrix.SetElement(1,1,meanNormal[1]) matrix.SetElement(2,1,meanNormal[2]) matrix.SetElement(3,1,0.0) matrix.SetElement(0,2,v2[0]) matrix.SetElement(1,2,v2[1]) matrix.SetElement(2,2,v2[2]) matrix.SetElement(3,2,0.0) matrix.SetElement(0,3,seed1[0]) matrix.SetElement(1,3,seed1[1]) matrix.SetElement(2,3,seed1[2]) matrix.SetElement(3,3,1.0) return True
def updateModelFromMarkup(self, inputMarkup, outputModel): """ Update model to enclose all points in the input markup list """ # Delaunay triangulation is robust and creates nice smooth surfaces from a small number of points, # however it can only generate convex surfaces robustly. useDelaunay = True # Create polydata point set from markup points points = vtk.vtkPoints() cellArray = vtk.vtkCellArray() numberOfPoints = inputMarkup.GetNumberOfFiducials() # Surface generation algorithms behave unpredictably when there are not enough points # return if there are very few points if useDelaunay: if numberOfPoints < 3: return else: if numberOfPoints < 10: return points.SetNumberOfPoints(numberOfPoints) new_coord = [0.0, 0.0, 0.0] for i in range(numberOfPoints): inputMarkup.GetNthFiducialPosition(i, new_coord) points.SetPoint(i, new_coord) cellArray.InsertNextCell(numberOfPoints) for i in range(numberOfPoints): cellArray.InsertCellPoint(i) pointPolyData = vtk.vtkPolyData() pointPolyData.SetLines(cellArray) pointPolyData.SetPoints(points) # Create surface from point set if useDelaunay: delaunay = vtk.vtkDelaunay3D() delaunay.SetInputData(pointPolyData) surfaceFilter = vtk.vtkDataSetSurfaceFilter() surfaceFilter.SetInputConnection(delaunay.GetOutputPort()) smoother = vtk.vtkButterflySubdivisionFilter() smoother.SetInputConnection(surfaceFilter.GetOutputPort()) smoother.SetNumberOfSubdivisions(3) smoother.Update() outputModel.SetPolyDataConnection(smoother.GetOutputPort()) else: surf = vtk.vtkSurfaceReconstructionFilter() surf.SetInputData(pointPolyData) surf.SetNeighborhoodSize(20) surf.SetSampleSpacing( 80 ) # lower value follows the small details more closely but more dense pointset is needed as input cf = vtk.vtkContourFilter() cf.SetInputConnection(surf.GetOutputPort()) cf.SetValue(0, 0.0) # Sometimes the contouring algorithm can create a volume whose gradient # vector and ordering of polygon (using the right hand rule) are # inconsistent. vtkReverseSense cures this problem. reverse = vtk.vtkReverseSense() reverse.SetInputConnection(cf.GetOutputPort()) reverse.ReverseCellsOff() reverse.ReverseNormalsOff() outputModel.SetPolyDataConnection(reverse.GetOutputPort()) # Create default model display node if does not exist yet if not outputModel.GetDisplayNode(): modelDisplayNode = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelDisplayNode") modelDisplayNode.SetColor(0, 0, 1) # Blue modelDisplayNode.BackfaceCullingOff() modelDisplayNode.SliceIntersectionVisibilityOn() modelDisplayNode.SetOpacity(0.3) # Between 0-1, 1 being opaque slicer.mrmlScene.AddNode(modelDisplayNode) outputModel.SetAndObserveDisplayNodeID(modelDisplayNode.GetID()) outputModel.GetDisplayNode().SliceIntersectionVisibilityOn() outputModel.Modified()
def createTumorFromMarkups(self): logging.debug('createTumorFromMarkups') #self.tumorMarkups_Needle.SetDisplayVisibility(0) # Create polydata point set from markup points points = vtk.vtkPoints() cellArray = vtk.vtkCellArray() numberOfPoints = self.tumorMarkups_Needle.GetNumberOfFiducials() if numberOfPoints > 0: self.deleteLastFiducialButton.setEnabled(True) self.deleteAllFiducialsButton.setEnabled(True) self.deleteLastFiducialDuringNavigationButton.setEnabled(True) # Surface generation algorithms behave unpredictably when there are not enough points # return if there are very few points if numberOfPoints < 1: return points.SetNumberOfPoints(numberOfPoints) new_coord = [0.0, 0.0, 0.0] for i in range(numberOfPoints): self.tumorMarkups_Needle.GetNthFiducialPosition(i, new_coord) points.SetPoint(i, new_coord) cellArray.InsertNextCell(numberOfPoints) for i in range(numberOfPoints): cellArray.InsertCellPoint(i) pointPolyData = vtk.vtkPolyData() pointPolyData.SetLines(cellArray) pointPolyData.SetPoints(points) delaunay = vtk.vtkDelaunay3D() if numberOfPoints < 10: logging.debug("use glyphs") sphere = vtk.vtkCubeSource() glyph = vtk.vtkGlyph3D() glyph.SetInputData(pointPolyData) glyph.SetSourceConnection(sphere.GetOutputPort()) #glyph.SetVectorModeToUseNormal() #glyph.SetScaleModeToScaleByVector() #glyph.SetScaleFactor(0.25) delaunay.SetInputConnection(glyph.GetOutputPort()) else: delaunay.SetInputData(pointPolyData) surfaceFilter = vtk.vtkDataSetSurfaceFilter() surfaceFilter.SetInputConnection(delaunay.GetOutputPort()) smoother = vtk.vtkButterflySubdivisionFilter() smoother.SetInputConnection(surfaceFilter.GetOutputPort()) smoother.SetNumberOfSubdivisions(3) smoother.Update() forceConvexShape = True if (forceConvexShape == True): delaunaySmooth = vtk.vtkDelaunay3D() delaunaySmooth.SetInputData(smoother.GetOutput()) delaunaySmooth.Update() smoothSurfaceFilter = vtk.vtkDataSetSurfaceFilter() smoothSurfaceFilter.SetInputConnection( delaunaySmooth.GetOutputPort()) self.tumorModel_Needle.SetPolyDataConnection( smoothSurfaceFilter.GetOutputPort()) else: self.tumorModel_Needle.SetPolyDataConnection( smoother.GetOutputPort()) self.tumorModel_Needle.Modified()
def createTumorFromMarkups(self): logging.debug("createTumorFromMarkups") # self.tumorMarkups_Needle.SetDisplayVisibility(0) # Create polydata point set from markup points points = vtk.vtkPoints() cellArray = vtk.vtkCellArray() numberOfPoints = self.tumorMarkups_Needle.GetNumberOfFiducials() if numberOfPoints > 0: self.deleteLastFiducialButton.setEnabled(True) self.deleteAllFiducialsButton.setEnabled(True) self.deleteLastFiducialDuringNavigationButton.setEnabled(True) # Surface generation algorithms behave unpredictably when there are not enough points # return if there are very few points if numberOfPoints < 1: return points.SetNumberOfPoints(numberOfPoints) new_coord = [0.0, 0.0, 0.0] for i in range(numberOfPoints): self.tumorMarkups_Needle.GetNthFiducialPosition(i, new_coord) points.SetPoint(i, new_coord) cellArray.InsertNextCell(numberOfPoints) for i in range(numberOfPoints): cellArray.InsertCellPoint(i) pointPolyData = vtk.vtkPolyData() pointPolyData.SetLines(cellArray) pointPolyData.SetPoints(points) delaunay = vtk.vtkDelaunay3D() if numberOfPoints < 10: logging.debug("use glyphs") sphere = vtk.vtkCubeSource() glyph = vtk.vtkGlyph3D() glyph.SetInputData(pointPolyData) glyph.SetSourceConnection(sphere.GetOutputPort()) # glyph.SetVectorModeToUseNormal() # glyph.SetScaleModeToScaleByVector() # glyph.SetScaleFactor(0.25) delaunay.SetInputConnection(glyph.GetOutputPort()) else: delaunay.SetInputData(pointPolyData) surfaceFilter = vtk.vtkDataSetSurfaceFilter() surfaceFilter.SetInputConnection(delaunay.GetOutputPort()) smoother = vtk.vtkButterflySubdivisionFilter() smoother.SetInputConnection(surfaceFilter.GetOutputPort()) smoother.SetNumberOfSubdivisions(3) smoother.Update() forceConvexShape = True if forceConvexShape == True: delaunaySmooth = vtk.vtkDelaunay3D() delaunaySmooth.SetInputData(smoother.GetOutput()) delaunaySmooth.Update() smoothSurfaceFilter = vtk.vtkDataSetSurfaceFilter() smoothSurfaceFilter.SetInputConnection(delaunaySmooth.GetOutputPort()) self.tumorModel_Needle.SetPolyDataConnection(smoothSurfaceFilter.GetOutputPort()) else: self.tumorModel_Needle.SetPolyDataConnection(smoother.GetOutputPort()) self.tumorModel_Needle.Modified()