def Smooth_Surface(self, surface): # Take a vtk surface and run it through the smoothing pipeline boneNormals = vtk.vtkPolyDataNormals() try: boneNormals.SetInputData(surface) except: boneNormals.SetInputConnection(surface.GetOutputPort()) boneNormals.Update() # Clean the polydata so that the edges are shared! cleanPolyData = vtk.vtkCleanPolyData() cleanPolyData.SetInputConnection(boneNormals.GetOutputPort()) cleanPolyData.Update() polydata = cleanPolyData.GetOutput() if self.smoothing_iterations > 0: # Apply laplacian smoothing to the surface smoothingFilter = vtk.vtkSmoothPolyDataFilter() smoothingFilter.SetInputData(polydata) smoothingFilter.SetNumberOfIterations( int(self.smoothing_iterations)) smoothingFilter.SetRelaxationFactor(self.relaxation_factor) smoothingFilter.Update() polydata = smoothingFilter.GetOutput() if self.decimate_surface > 0 and self.decimate_surface < 1: # We want to preserve topology (not let any cracks form). This may # limit the total reduction possible, which we have specified at 80%. deci = vtk.vtkDecimatePro() deci.SetInputData(polydata) deci.SetTargetReduction(self.decimate_surface) deci.PreserveTopologyOn() deci.Update() polydata = deci.GetOutput() # Clean the polydata so that the edges are shared! cleanPolyData = vtk.vtkCleanPolyData() cleanPolyData.SetInputData(polydata) cleanPolyData.Update() polydata = cleanPolyData.GetOutput() # Generate surface normals to give a better visualization normals = vtk.vtkPolyDataNormals() normals.SetInputData(polydata) normals.Update() polydata = normals.GetOutput() return polydata
def applyFilters(self, state): surface = state.inputModelNode.GetPolyData() if state.decimation: triangle = vtk.vtkTriangleFilter() triangle.SetInput(surface) decimation = vtk.vtkDecimatePro() decimation.SetInput(triangle.GetOutput()) decimation.SetTargetReduction(state.reduction) decimation.SetBoundaryVertexDeletion(state.boundaryDeletion) decimation.PreserveTopologyOn() decimation.Update() surface = decimation.GetOutput() if state.smoothing: if state.smoothingMethod == "Laplace": smoothing = vtk.vtkSmoothPolyDataFilter() smoothing.SetInput(surface) smoothing.SetBoundarySmoothing(state.boundarySmoothing) smoothing.SetNumberOfIterations(state.laplaceIterations) smoothing.SetRelaxationFactor(state.laplaceRelaxation) smoothing.Update() surface = smoothing.GetOutput() elif state.smoothingMethod == "Taubin": smoothing = vtk.vtkWindowedSincPolyDataFilter() smoothing.SetInput(surface) smoothing.SetBoundarySmoothing(state.boundarySmoothing) smoothing.SetNumberOfIterations(state.taubinIterations) smoothing.SetPassBand(state.taubinPassBand) smoothing.Update() surface = smoothing.GetOutput() if state.normals: normals = vtk.vtkPolyDataNormals() normals.SetInput(surface) normals.AutoOrientNormalsOn() normals.SetFlipNormals(state.flipNormals) normals.SetSplitting(state.splitting) normals.SetFeatureAngle(state.featureAngle) normals.ConsistencyOn() normals.Update() surface = normals.GetOutput() if state.cleaner: cleaner = vtk.vtkCleanPolyData() cleaner.SetInput(surface) cleaner.Update() surface = cleaner.GetOutput() if state.connectivity: connectivity = vtk.vtkPolyDataConnectivityFilter() connectivity.SetInput(surface) connectivity.SetExtractionModeToLargestRegion() connectivity.Update() surface = connectivity.GetOutput() state.outputModelNode.SetAndObservePolyData(surface) return True
def prepareModel( self, polyData ): ''' ''' # import the vmtk libraries try: #from libvtkvmtkComputationalGeometryPython import * #from libvtkvmtkMiscPython import * import libvtkvmtkComputationalGeometryPython as cg import libvtkvmtkMiscPython as m except ImportError: print "FAILURE: Unable to import the SlicerVmtk libraries!" capDisplacement = 0.0 surfaceCleaner = vtk.vtkCleanPolyData() surfaceCleaner.SetInput( polyData ) surfaceCleaner.Update() surfaceTriangulator = vtk.vtkTriangleFilter() surfaceTriangulator.SetInput( surfaceCleaner.GetOutput() ) surfaceTriangulator.PassLinesOff() surfaceTriangulator.PassVertsOff() surfaceTriangulator.Update() # new steps for preparation to avoid problems because of slim models (f.e. at stenosis) subdiv = vtk.vtkLinearSubdivisionFilter() subdiv.SetInput( surfaceTriangulator.GetOutput() ) subdiv.SetNumberOfSubdivisions( 1 ) subdiv.Update() smooth = vtk.vtkWindowedSincPolyDataFilter() smooth.SetInput( subdiv.GetOutput() ) smooth.SetNumberOfIterations( 20 ) smooth.SetPassBand( 0.1 ) smooth.SetBoundarySmoothing( 1 ) smooth.Update() normals = vtk.vtkPolyDataNormals() normals.SetInput( smooth.GetOutput() ) normals.SetAutoOrientNormals( 1 ) normals.SetFlipNormals( 0 ) normals.SetConsistency( 1 ) normals.SplittingOff() normals.Update() surfaceCapper = m.vtkvmtkCapPolyData() surfaceCapper.SetInput( normals.GetOutput() ) surfaceCapper.SetDisplacement( capDisplacement ) surfaceCapper.SetInPlaneDisplacement( capDisplacement ) surfaceCapper.Update() outPolyData = vtk.vtkPolyData() outPolyData.DeepCopy( surfaceCapper.GetOutput() ) outPolyData.Update() return outPolyData
def polydataBoolean(self, polyData1, polyData2, operation, triangleFilter=False, loop=False, clean=True): # Subtract/add polyData2 from polyData1 if (not polyData1) or (not polyData2): return polyData1 booleanFilter = vtk.vtkBooleanOperationPolyDataFilter() if loop: booleanFilter = vtk.vtkLoopBooleanPolyDataFilter() if operation == "difference" or operation == "subtract": booleanFilter.SetOperationToDifference() elif operation == "union" or operation == "addition": booleanFilter.SetOperationToUnion() elif operation == "intersection": booleanFilter.SetOperationToIntersection() else: return None if triangleFilter: triangleFilter1 = vtk.vtkTriangleFilter() triangleFilter1.SetInputData(polyData1) triangleFilter1.Update() triangleFilter2 = vtk.vtkTriangleFilter() triangleFilter2.SetInputData(polyData2) triangleFilter2.Update() booleanFilter.SetInputData(0, triangleFilter1.GetOutput()) booleanFilter.SetInputData(1, triangleFilter2.GetOutput()) else: booleanFilter.SetInputData(0, polyData1) booleanFilter.SetInputData(1, polyData2) booleanFilter.Update() if clean: cleanFilter = vtk.vtkCleanPolyData() cleanFilter.SetInputData(booleanFilter.GetOutput()) cleanFilter.PointMergingOn() cleanFilter.Update() print("blah") return cleanFilter.GetOutput() else: return booleanFilter.GetOutput()
def vtkCleanPolyData(self, inputModelNode, tolerance, runtimeLabel): runtime = vtk.vtkTimerLog() runtime.StartTimer() # vtkVertexGlyphFilter glyphFilter = vtk.vtkVertexGlyphFilter() glyphFilter.SetInputConnection(inputModelNode.GetPolyDataConnection()) # vtkCleanPolyData cleanPolyData = vtk.vtkCleanPolyData() cleanPolyData.SetInputConnection(glyphFilter.GetOutputPort()) cleanPolyData.SetTolerance(tolerance) cleanPolyData.Update() runtime.StopTimer() runtimeLabel.setText('vtkCleanPolyData computed in %.2f' % runtime.GetElapsedTime() + ' s.') inputModelNode.SetAndObservePolyData(cleanPolyData.GetOutput())
def GetBoundaryPoints( self, inPolyData ): featureEdges = vtk.vtkFeatureEdges() featureEdges.FeatureEdgesOff() featureEdges.NonManifoldEdgesOff() featureEdges.ManifoldEdgesOff() featureEdges.BoundaryEdgesOn() featureEdges.SetInputData( inPolyData ) featureEdges.Update() stripper = vtk.vtkStripper() stripper.SetInputData( featureEdges.GetOutput() ) stripper.Update() cleaner = vtk.vtkCleanPolyData() cleaner.SetInputData( stripper.GetOutput() ) cleaner.Update() return cleaner.GetOutput().GetPoints()
def decimateSurface( self, polyData ): ''' ''' decimationFilter = vtk.vtkDecimatePro() decimationFilter.SetInputData( polyData ) decimationFilter.SetTargetReduction( 0.99 ) decimationFilter.SetBoundaryVertexDeletion( 0 ) decimationFilter.PreserveTopologyOn() decimationFilter.Update() cleaner = vtk.vtkCleanPolyData() cleaner.SetInputData( decimationFilter.GetOutput() ) cleaner.Update() triangleFilter = vtk.vtkTriangleFilter() triangleFilter.SetInputData( cleaner.GetOutput() ) triangleFilter.Update() outPolyData = vtk.vtkPolyData() outPolyData.DeepCopy( triangleFilter.GetOutput() ) return outPolyData
def clipSurfaceAtEndPoints(self, networkPolyData, surfacePolyData): ''' Clips the surfacePolyData on the endpoints identified using the networkPolyData. Returns a tupel of the form [clippedPolyData, endpointsPoints] ''' # import the vmtk libraries try: from libvtkvmtkComputationalGeometryPython import * from libvtkvmtkMiscPython import * except ImportError: print "FAILURE: Unable to import the SlicerVmtk4 libraries!" cleaner = vtk.vtkCleanPolyData() cleaner.SetInput(networkPolyData) cleaner.Update() network = cleaner.GetOutput() network.BuildCells() network.BuildLinks(0) endpointIds = vtk.vtkIdList() radiusArray = network.GetPointData().GetArray('Radius') endpoints = vtk.vtkPolyData() endpointsPoints = vtk.vtkPoints() endpointsRadius = vtk.vtkDoubleArray() endpointsRadius.SetName('Radius') endpoints.SetPoints(endpointsPoints) endpoints.GetPointData().AddArray(endpointsRadius) radiusFactor = 1.2 minRadius = 0.01 for i in range(network.GetNumberOfCells()): numberOfCellPoints = network.GetCell(i).GetNumberOfPoints() pointId0 = network.GetCell(i).GetPointId(0) pointId1 = network.GetCell(i).GetPointId(numberOfCellPoints - 1) pointCells = vtk.vtkIdList() network.GetPointCells(pointId0, pointCells) numberOfEndpoints = endpointIds.GetNumberOfIds() if pointCells.GetNumberOfIds() == 1: pointId = endpointIds.InsertUniqueId(pointId0) if pointId == numberOfEndpoints: point = network.GetPoint(pointId0) radius = radiusArray.GetValue(pointId0) radius = max(radius, minRadius) endpointsPoints.InsertNextPoint(point) endpointsRadius.InsertNextValue(radiusFactor * radius) pointCells = vtk.vtkIdList() network.GetPointCells(pointId1, pointCells) numberOfEndpoints = endpointIds.GetNumberOfIds() if pointCells.GetNumberOfIds() == 1: pointId = endpointIds.InsertUniqueId(pointId1) if pointId == numberOfEndpoints: point = network.GetPoint(pointId1) radius = radiusArray.GetValue(pointId1) radius = max(radius, minRadius) endpointsPoints.InsertNextPoint(point) endpointsRadius.InsertNextValue(radiusFactor * radius) polyBall = vtkvmtkPolyBall() polyBall.SetInput(endpoints) polyBall.SetPolyBallRadiusArrayName('Radius') clipper = vtk.vtkClipPolyData() clipper.SetInput(surfacePolyData) clipper.SetClipFunction(polyBall) clipper.Update() connectivityFilter = vtk.vtkPolyDataConnectivityFilter() connectivityFilter.SetInput(clipper.GetOutput()) connectivityFilter.ColorRegionsOff() connectivityFilter.SetExtractionModeToLargestRegion() connectivityFilter.Update() clippedSurface = connectivityFilter.GetOutput() outPolyData = vtk.vtkPolyData() outPolyData.DeepCopy(clippedSurface) outPolyData.Update() return [outPolyData, endpointsPoints]
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 clipSurfaceAtEndPoints( self, networkPolyData, surfacePolyData ): ''' Clips the surfacePolyData on the endpoints identified using the networkPolyData. Returns a tupel of the form [clippedPolyData, endpointsPoints] ''' # import the vmtk libraries try: import vtkvmtkComputationalGeometryPython as vtkvmtkComputationalGeometry import vtkvmtkMiscPython as vtkvmtkMisc except ImportError: logging.error("Unable to import the SlicerVmtk libraries") cleaner = vtk.vtkCleanPolyData() cleaner.SetInputData( networkPolyData ) cleaner.Update() network = cleaner.GetOutput() network.BuildCells() network.BuildLinks( 0 ) endpointIds = vtk.vtkIdList() radiusArray = network.GetPointData().GetArray( 'Radius' ) endpoints = vtk.vtkPolyData() endpointsPoints = vtk.vtkPoints() endpointsRadius = vtk.vtkDoubleArray() endpointsRadius.SetName( 'Radius' ) endpoints.SetPoints( endpointsPoints ) endpoints.GetPointData().AddArray( endpointsRadius ) radiusFactor = 1.2 minRadius = 0.01 for i in range( network.GetNumberOfCells() ): numberOfCellPoints = network.GetCell( i ).GetNumberOfPoints() pointId0 = network.GetCell( i ).GetPointId( 0 ) pointId1 = network.GetCell( i ).GetPointId( numberOfCellPoints - 1 ) pointCells = vtk.vtkIdList() network.GetPointCells( pointId0, pointCells ) numberOfEndpoints = endpointIds.GetNumberOfIds() if pointCells.GetNumberOfIds() == 1: pointId = endpointIds.InsertUniqueId( pointId0 ) if pointId == numberOfEndpoints: point = network.GetPoint( pointId0 ) radius = radiusArray.GetValue( pointId0 ) radius = max( radius, minRadius ) endpointsPoints.InsertNextPoint( point ) endpointsRadius.InsertNextValue( radiusFactor * radius ) pointCells = vtk.vtkIdList() network.GetPointCells( pointId1, pointCells ) numberOfEndpoints = endpointIds.GetNumberOfIds() if pointCells.GetNumberOfIds() == 1: pointId = endpointIds.InsertUniqueId( pointId1 ) if pointId == numberOfEndpoints: point = network.GetPoint( pointId1 ) radius = radiusArray.GetValue( pointId1 ) radius = max( radius, minRadius ) endpointsPoints.InsertNextPoint( point ) endpointsRadius.InsertNextValue( radiusFactor * radius ) polyBall = vtkvmtkComputationalGeometry.vtkvmtkPolyBall() #polyBall.SetInputData( endpoints ) polyBall.SetInput( endpoints ) polyBall.SetPolyBallRadiusArrayName( 'Radius' ) clipper = vtk.vtkClipPolyData() clipper.SetInputData( surfacePolyData ) clipper.SetClipFunction( polyBall ) clipper.Update() connectivityFilter = vtk.vtkPolyDataConnectivityFilter() connectivityFilter.SetInputData( clipper.GetOutput() ) connectivityFilter.ColorRegionsOff() connectivityFilter.SetExtractionModeToLargestRegion() connectivityFilter.Update() clippedSurface = connectivityFilter.GetOutput() outPolyData = vtk.vtkPolyData() outPolyData.DeepCopy( clippedSurface ) return [outPolyData, endpointsPoints]
def run(self, inputModel, spherePosition, sphereRadius, outputTransform): """ Run the actual algorithm """ if not self.isValidInputOutputData(inputModel, outputTransform): slicer.util.errorDisplay( 'Input model is the same as sphere model. Choose a different input model.' ) return False logging.info('Processing started') # Convert sphere model to an implicit dataset to clip input model with it sphere = vtk.vtkSphere() sphere.SetCenter(spherePosition) sphere.SetRadius(sphereRadius) # Clip and clean input model triangle = vtk.vtkTriangleFilter() triangle.SetInputData(inputModel.GetPolyData()) triangle.Update() clip = vtk.vtkClipPolyData() clip.SetInputData(triangle.GetOutput()) clip.SetClipFunction(sphere) clip.InsideOutOn() clip.Update() clean = vtk.vtkCleanPolyData() clean.SetInputConnection(clip.GetOutputPort()) clean.Update() # Compute average normal clippedModel = clip.GetOutput() cellsNormal = clippedModel.GetPointData().GetNormals() averageNormal = [0.0, 0.0, 0.0] nOfNormals = 0 for cellIndex in range(0, cellsNormal.GetNumberOfTuples()): cellNormal = [0.0, 0.0, 0.0] cellsNormal.GetTuple(cellIndex, cellNormal) if not (math.isnan(cellNormal[0]) or math.isnan(cellNormal[1]) or math.isnan(cellNormal[2])): averageNormal[0] = averageNormal[0] + cellNormal[0] averageNormal[1] = averageNormal[1] + cellNormal[1] averageNormal[2] = averageNormal[2] + cellNormal[2] nOfNormals = nOfNormals + 1 # Compute perpendicular vectors v1 = [0.0, 0.0, 0.0] v2 = [0.0, 0.0, 0.0] vtkmath = vtk.vtkMath() #vtkmath.Perpendiculars(averageNormal, v2, v1, 0) self.calculatePerpendicularVectors(averageNormal, v2, v1) # Normalize vectors vtkmath.Normalize(averageNormal) vtkmath.Normalize(v1) vtkmath.Normalize(v2) # Create Matrix4x4 outputMatrix = vtk.vtkMatrix4x4() outputMatrix.SetElement(0, 0, v1[0]) outputMatrix.SetElement(1, 0, v1[1]) outputMatrix.SetElement(2, 0, v1[2]) outputMatrix.SetElement(3, 0, 0.0) outputMatrix.SetElement(0, 1, averageNormal[0]) outputMatrix.SetElement(1, 1, averageNormal[1]) outputMatrix.SetElement(2, 1, averageNormal[2]) outputMatrix.SetElement(3, 1, 0.0) outputMatrix.SetElement(0, 2, v2[0]) outputMatrix.SetElement(1, 2, v2[1]) outputMatrix.SetElement(2, 2, v2[2]) outputMatrix.SetElement(3, 2, 0.0) outputMatrix.SetElement(0, 3, spherePosition[0]) outputMatrix.SetElement(1, 3, spherePosition[1]) outputMatrix.SetElement(2, 3, spherePosition[2]) outputMatrix.SetElement(3, 3, 1.0) outputTransform.SetMatrixTransformToParent(outputMatrix) logging.info('Processing completed') return True
def run( self, markupNode, depth, fitPlane, flip ): """ Run the actual algorithm """ # Get all of the fiducial nodes and convert to vtkPoints points = vtk.vtkPoints() for i in range( 0, markupNode.GetNumberOfFiducials() ): currentCoordinates = [ 0, 0, 0 ] markupNode.GetNthFiducialPosition( i, currentCoordinates ) points.InsertNextPoint( currentCoordinates ) # Check that there is non-zero range in all coordinate directions pointsBounds = [ 0, 0, 0, 0, 0, 0 ] points.GetBounds( pointsBounds ) if ( pointsBounds[0] == pointsBounds [1] or pointsBounds[2] == pointsBounds [3] or pointsBounds[4] == pointsBounds [5] ): print "Tissue Model Creator: Points have no extent in one or more coordinate directions." return False # Create a polydata object from the points # The reversiness doesn't matter - we will fix it later if it os wrong if ( fitPlane ): surfacePolyData = self.PointsToPlanePolyData( points, True ) else: surfacePolyData = self.PointsToSurfacePolyData( points, True ) surfaceCleaner = vtk.vtkCleanPolyData() surfaceCleaner.SetInputData( surfacePolyData ) surfaceCleaner.Update() surfacePolyData = surfaceCleaner.GetOutput() mean = self.CalculateMean( points ) surfaceBase = [ 0, 0, 0 ] surfaceDir1 = [ 0, 0, 0 ] surfaceDir2 = [ 0, 0, 0 ] surfaceNormal = [ 0, 0, 0 ] self.CalculatePlane( surfacePolyData.GetPoints(), surfaceBase, surfaceDir1, surfaceDir2, surfaceNormal ) if ( flip == True ): surfaceNormal[ 0 ] = - surfaceNormal[ 0 ] surfaceNormal[ 1 ] = - surfaceNormal[ 1 ] surfaceNormal[ 2 ] = - surfaceNormal[ 2 ] extremePointIndex = self.FindExtremePoint( surfacePolyData.GetPoints(), surfaceBase, surfaceNormal ) reverse = self.ReverseNormals( extremePointIndex, surfacePolyData, surfaceNormal ) # Reverse the normals if necessary reverseFilter = vtk.vtkReverseSense() reverseFilter.SetInputData( surfacePolyData ) reverseFilter.SetReverseCells( reverse ) reverseFilter.SetReverseNormals( reverse ) reverseFilter.Update() surfacePolyData = reverseFilter.GetOutput() untransDeepPolyData = vtk.vtkPolyData() untransDeepPolyData.DeepCopy( surfacePolyData ) # Make the normals opposite the surface's normals reverseFilter = vtk.vtkReverseSense() reverseFilter.SetInputData( untransDeepPolyData ) reverseFilter.SetReverseCells( True ) reverseFilter.SetReverseNormals( True ) reverseFilter.Update() untransDeepPolyData = reverseFilter.GetOutput() deepTransform = vtk.vtkTransform() deepTransform.Translate( depth * surfaceNormal[0], depth * surfaceNormal[1], depth * surfaceNormal[2] ) deepTransformFilter = vtk.vtkTransformPolyDataFilter() deepTransformFilter.SetInputData( untransDeepPolyData ) deepTransformFilter.SetTransform( deepTransform ) deepTransformFilter.Update() deepPolyData = deepTransformFilter.GetOutput() surfaceHullPoints = self.GetBoundaryPoints( surfacePolyData ) deepHullPoints = self.GetBoundaryPoints( deepPolyData ) # Apparently, the joining needs an offset for the plane, but not for the surface reconstruction if ( fitPlane ): jointHullPolyData = self.JoinBoundaryPoints( surfaceHullPoints, deepHullPoints, 1 ) else: jointHullPolyData = self.JoinBoundaryPoints( surfaceHullPoints, deepHullPoints, 0 ) # Append all of the polydata together tissuePolyDataAppend = vtk.vtkAppendPolyData() tissuePolyDataAppend.AddInputData( surfacePolyData ) tissuePolyDataAppend.AddInputData( deepPolyData ) tissuePolyDataAppend.AddInputData( jointHullPolyData ) tissuePolyDataAppend.Update() # Clean up so the surface is closed tissueCleaner = vtk.vtkCleanPolyData() tissueCleaner.SetInputData( tissuePolyDataAppend.GetOutput() ) tissueCleaner.Update() tissueModelPolyData = tissueCleaner.GetOutput() # Add the data to a model tissueModel = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelNode" ) slicer.mrmlScene.AddNode( tissueModel ) tissueModel.SetName( "TissueModel" ) tissueModel.SetAndObservePolyData( tissueModelPolyData ) tissueModel.SetScene( slicer.mrmlScene ) # Finally display the model tissueModelDisplay = slicer.mrmlScene.CreateNodeByClass( "vtkMRMLModelDisplayNode" ) slicer.mrmlScene.AddNode( tissueModelDisplay ) tissueModel.SetAndObserveDisplayNodeID( tissueModelDisplay.GetID() ) tissueModelDisplay.SetScene( slicer.mrmlScene ) tissueModelDisplay.SetInputPolyDataConnection( tissueModel.GetPolyDataConnection() ) # Check to make sure the model is a closed surface edgesFilter = vtk.vtkFeatureEdges() edgesFilter.FeatureEdgesOff() edgesFilter.BoundaryEdgesOn() edgesFilter.NonManifoldEdgesOn() edgesFilter.SetInputData( tissueModel.GetPolyData() ) edgesFilter.Update() if ( edgesFilter.GetOutput().GetNumberOfCells() != 0 ): print "Tissue Model Creator: Surface is not closed." return False return True
def run(self, inputModel, spherePosition, sphereRadius, outputTransform): """ Run the actual algorithm """ if not self.isValidInputOutputData(inputModel, outputTransform): slicer.util.errorDisplay('Input model is the same as sphere model. Choose a different input model.') return False logging.info('Processing started') # Convert sphere model to an implicit dataset to clip input model with it sphere = vtk.vtkSphere() sphere.SetCenter(spherePosition) sphere.SetRadius(sphereRadius) # Clip and clean input model triangle = vtk.vtkTriangleFilter() triangle.SetInputData(inputModel.GetPolyData()) triangle.Update() clip = vtk.vtkClipPolyData() clip.SetInputData(triangle.GetOutput()) clip.SetClipFunction(sphere) clip.InsideOutOn() clip.Update() clean = vtk.vtkCleanPolyData() clean.SetInputConnection(clip.GetOutputPort()) clean.Update() # Compute average normal clippedModel = clip.GetOutput() cellsNormal = clippedModel.GetPointData().GetNormals() averageNormal = [0.0, 0.0, 0.0] nOfNormals = 0; for cellIndex in range(0, cellsNormal.GetNumberOfTuples()): cellNormal = [0.0, 0.0, 0.0] cellsNormal.GetTuple(cellIndex, cellNormal) if not(math.isnan(cellNormal[0]) or math.isnan(cellNormal[1]) or math.isnan(cellNormal[2])): averageNormal[0] = averageNormal[0] + cellNormal[0] averageNormal[1] = averageNormal[1] + cellNormal[1] averageNormal[2] = averageNormal[2] + cellNormal[2] nOfNormals = nOfNormals + 1 # Compute perpendicular vectors v1 = [0.0, 0.0, 0.0] v2 = [0.0, 0.0, 0.0] vtkmath = vtk.vtkMath() #vtkmath.Perpendiculars(averageNormal, v2, v1, 0) self.calculatePerpendicularVectors(averageNormal, v2, v1) # Normalize vectors vtkmath.Normalize(averageNormal) vtkmath.Normalize(v1) vtkmath.Normalize(v2) # Create Matrix4x4 outputMatrix = vtk.vtkMatrix4x4() outputMatrix.SetElement(0,0,v1[0]) outputMatrix.SetElement(1,0,v1[1]) outputMatrix.SetElement(2,0,v1[2]) outputMatrix.SetElement(3,0,0.0) outputMatrix.SetElement(0,1,averageNormal[0]) outputMatrix.SetElement(1,1,averageNormal[1]) outputMatrix.SetElement(2,1,averageNormal[2]) outputMatrix.SetElement(3,1,0.0) outputMatrix.SetElement(0,2,v2[0]) outputMatrix.SetElement(1,2,v2[1]) outputMatrix.SetElement(2,2,v2[2]) outputMatrix.SetElement(3,2,0.0) outputMatrix.SetElement(0,3,spherePosition[0]) outputMatrix.SetElement(1,3,spherePosition[1]) outputMatrix.SetElement(2,3,spherePosition[2]) outputMatrix.SetElement(3,3,1.0) outputTransform.SetMatrixTransformToParent(outputMatrix) logging.info('Processing completed') return True