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 updateCurve(self): if self.controlPointsMarkupNode and self.curveModelNode: self.curvePoints.Reset() # clear without deallocating memory lines = vtk.vtkCellArray() self.curvePoly.SetLines(lines) if self.controlPointsMarkupNode.GetNumberOfFiducials() >= 2: self.pointInterpolationFunction(self.controlPointsMarkupNode, self.curvePoints) nInterpolatedPoints = self.curvePoints.GetNumberOfPoints() lines.InsertNextCell(nInterpolatedPoints) for i in range(nInterpolatedPoints): lines.InsertCellPoint(i) tubeFilter = vtk.vtkTubeFilter() tubeFilter.SetInputData(self.curvePoly) tubeFilter.SetRadius(self.tubeRadius) tubeFilter.SetNumberOfSides(self.tubeResolution) tubeFilter.SetCapping(not self.closed) # Triangulation is necessary to avoid discontinuous lines # in model/slice intersection display triangles = vtk.vtkTriangleFilter() triangles.SetInputConnection(tubeFilter.GetOutputPort()) triangles.Update() self.curveModelNode.SetAndObservePolyData(triangles.GetOutput()) self.curveModelNode.Modified()
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 runModelToLabelMap(self,image, modelNode, outputMask, refineRate): # Make sure all polygons are triangles triangle = vtk.vtkTriangleFilter() triangle.SetInput(modelNode.GetPolyData()) triangle.Update() modelNode.SetAndObservePolyData(triangle.GetOutput()) # Increase number of polygons in the mesh to avoid having holes # in contour, which confuse ModelToLabelMap when flooding # (flooding the whole labelmap if contour is not closed) refine = vtk.vtkLoopSubdivisionFilter() refine.SetInput(modelNode.GetPolyData()) refine.SetNumberOfSubdivisions(refineRate) refine.Update() modelNode.SetAndObservePolyData(refine.GetOutput()) # Set ModelToLabelMap parameters modelToLabelMapParameters["InputVolume"] = image.GetID() modelToLabelMapParameters["surface"] = modelNode.GetID() modelToLabelMapParameters["OutputVolume"] = outputMask.GetID() # Run ModelToLabelMap modelToLabelMapCLI = slicer.modules.modeltolabelmap slicer.cli.run(modelToLabelMapCLI, None, modelToLabelMapParameters, wait_for_completion=True)
def calculateSurfaceArea(polydata): triangleFilter = vtk.vtkTriangleFilter() triangleFilter.SetInputData(polydata) triangleFilter.SetPassLines(0) triangleFilter.Update() massProperties = vtk.vtkMassProperties() massProperties.SetInputData(triangleFilter.GetOutput()) return massProperties.GetSurfaceArea()
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 createBox(X, Y, Z, name): miterBox = slicer.mrmlScene.CreateNodeByClass('vtkMRMLModelNode') miterBox.SetName(slicer.mrmlScene.GetUniqueNameByString(name)) slicer.mrmlScene.AddNode(miterBox) miterBox.CreateDefaultDisplayNodes() miterBoxSource = vtk.vtkCubeSource() miterBoxSource.SetXLength(X) miterBoxSource.SetYLength(Y) miterBoxSource.SetZLength(Z) triangleFilter = vtk.vtkTriangleFilter() triangleFilter.SetInputConnection(miterBoxSource.GetOutputPort()) #triangleFilter.Update() miterBox.SetPolyDataConnection(triangleFilter.GetOutputPort()) return miterBox
def computeSurfaceBetweenLines(self): """ Update model with a surface between base and margin lines. """ numberOfBasePoints = self.baseLine.curvePoints.GetNumberOfPoints() numberOfMarginPoints = self.marginLine.curvePoints.GetNumberOfPoints() if numberOfBasePoints == 0 or numberOfMarginPoints == 0: self.surfaceModelNode.SetAndObservePolyData(None) return boundaryPoints = vtk.vtkPoints() boundaryPoints.DeepCopy(self.baseLine.curvePoints) boundaryPoints.InsertPoints(numberOfBasePoints, numberOfMarginPoints, 0, self.marginLine.curvePoints) # Add a triangle strip between the base and margin lines strips = vtk.vtkCellArray() strips.InsertNextCell(numberOfBasePoints * 2) basePointToMarginPointScale = float(numberOfMarginPoints) / float( numberOfBasePoints) for basePointIndex in range(numberOfBasePoints): strips.InsertCellPoint(basePointIndex) strips.InsertCellPoint( int(numberOfBasePoints + basePointIndex * basePointToMarginPointScale)) clippingSurfacePolyData = vtk.vtkPolyData() clippingSurfacePolyData.SetPoints(boundaryPoints) clippingSurfacePolyData.SetStrips(strips) triangulator = vtk.vtkTriangleFilter() triangulator.SetInputData(clippingSurfacePolyData) triangulator.Update() clippingPolyData = triangulator.GetOutput() self.surfaceModelNode.SetAndObservePolyData(clippingPolyData)
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 updateRoi(self): if not self.roiModelNode: return numberOfContourPoints = 0 annulusPoints = None planePosition = None planeNormal = None if self.annulusContourCurve: contourPoints = self.annulusContourCurve.curvePoints # vtk.vtkPoints() numberOfContourPoints = contourPoints.GetNumberOfPoints() if numberOfContourPoints > 0: annulusPoints = self.annulusContourCurve.getInterpolatedPointsAsArray( ) # formerly contourPointsArray_Ras [planePosition, planeNormal] = HeartValveLib.planeFit(annulusPoints) elif self.valveModel is not None and self.leafletSegmentId is not None: annulusPoints = self.getLeafletBoundary() if annulusPoints is not None: numberOfContourPoints = annulusPoints.shape[1] [planePosition, planeNormal] = self.valveModel.getAnnulusContourPlane() if numberOfContourPoints <= 0: clippingPolyData = vtk.vtkPolyData() self.roiModelNode.SetAndObservePolyData(clippingPolyData) self.roiModelNode.Modified() return scale = float(self.roiModelNode.GetAttribute(self.PARAM_SCALE)) * 0.01 topDistance = float( self.roiModelNode.GetAttribute(self.PARAM_TOP_DISTANCE)) topScale = float(self.roiModelNode.GetAttribute( self.PARAM_TOP_SCALE)) * 0.01 bottomDistance = float( self.roiModelNode.GetAttribute(self.PARAM_BOTTOM_DISTANCE)) bottomScale = float( self.roiModelNode.GetAttribute(self.PARAM_BOTTOM_SCALE)) * 0.01 transformPlaneToWorld = vtk.vtkTransform() transformWorldToPlaneMatrix = HeartValveLib.getTransformToPlane( planePosition, planeNormal) numberOfPoints = annulusPoints.shape[1] # Concatenate a 4th line containing 1s so that we can transform the positions using # a single matrix multiplication. annulusPoints_World = np.row_stack( (annulusPoints, np.ones(numberOfPoints))) # Point positions in the plane coordinate system: annulusPoints_Plane = np.dot(transformWorldToPlaneMatrix, annulusPoints_World) # remove the last row (all ones) annulusPoints_Plane = annulusPoints_Plane[0:3, :] # Add points for middle, top, and bottom planes clippingSurfacePoints = vtk.vtkPoints() clippingSurfacePoints.Allocate( 3 * numberOfContourPoints ) # annulus contour + 2x shifted annulus contour # Middle plane annulusPoints_Plane[0, :] = ( annulusPoints_Plane[0, :] - annulusPoints_Plane[0, :].mean() ) * scale + annulusPoints_Plane[0, :].mean() annulusPoints_Plane[1, :] = ( annulusPoints_Plane[1, :] - annulusPoints_Plane[1, :].mean() ) * scale + annulusPoints_Plane[1, :].mean() for contourPoint in annulusPoints_Plane.T: clippingSurfacePoints.InsertNextPoint(contourPoint) meanPosZ = annulusPoints_Plane[:, 2].mean() # Top plane contourPointsArrayTop_Ras = np.copy(annulusPoints_Plane) contourPointsArrayTop_Ras[0, :] = ( contourPointsArrayTop_Ras[0, :] - annulusPoints_Plane[0, :].mean() ) * topScale + annulusPoints_Plane[0, :].mean() contourPointsArrayTop_Ras[1, :] = ( contourPointsArrayTop_Ras[1, :] - annulusPoints_Plane[1, :].mean() ) * topScale + annulusPoints_Plane[1, :].mean() contourPointsArrayTop_Ras[2, :] = topDistance # make the plane planar for contourPoint in contourPointsArrayTop_Ras.T: clippingSurfacePoints.InsertNextPoint(contourPoint) # Bottom plane contourPointsArrayBottom_Ras = np.copy(annulusPoints_Plane) contourPointsArrayBottom_Ras[ 0, :] = (contourPointsArrayBottom_Ras[0, :] - annulusPoints_Plane[ 0, :].mean()) * bottomScale + annulusPoints_Plane[0, :].mean() contourPointsArrayBottom_Ras[ 1, :] = (contourPointsArrayBottom_Ras[1, :] - annulusPoints_Plane[ 1, :].mean()) * bottomScale + annulusPoints_Plane[1, :].mean() contourPointsArrayBottom_Ras[ 2, :] = -bottomDistance # make the plane planar for contourPoint in contourPointsArrayBottom_Ras.T: clippingSurfacePoints.InsertNextPoint(contourPoint) # Add frustum surfaces strips = vtk.vtkCellArray() # Between middle and top strips.InsertNextCell(numberOfContourPoints * 2 + 2) firstTopPointIndex = numberOfContourPoints for i in range(numberOfContourPoints): strips.InsertCellPoint(i) strips.InsertCellPoint(i + firstTopPointIndex) strips.InsertCellPoint(0) strips.InsertCellPoint(firstTopPointIndex) # Between middle and bottom strips.InsertNextCell(numberOfContourPoints * 2 + 2) firstBottomPointIndex = numberOfContourPoints * 2 for i in range(numberOfContourPoints): strips.InsertCellPoint(i) strips.InsertCellPoint(i + firstBottomPointIndex) strips.InsertCellPoint(0) strips.InsertCellPoint(firstBottomPointIndex) # Top and bottom caps polys = vtk.vtkCellArray() polys.InsertNextCell(numberOfContourPoints) for i in range(numberOfContourPoints, numberOfContourPoints * 2): polys.InsertCellPoint(i) polys.InsertNextCell(numberOfContourPoints) for i in range(numberOfContourPoints * 2, numberOfContourPoints * 3): polys.InsertCellPoint(i) clippingSurfacePolyData = vtk.vtkPolyData() clippingSurfacePolyData.SetPoints(clippingSurfacePoints) clippingSurfacePolyData.SetStrips(strips) clippingSurfacePolyData.SetPolys(polys) triangulator = vtk.vtkTriangleFilter() triangulator.SetInputData(clippingSurfacePolyData) transformPlaneToWorldMatrix = np.linalg.inv( transformWorldToPlaneMatrix) transformPlaneToWorldMatrixVtk = vtk.vtkMatrix4x4() for colIndex in range(4): for rowIndex in range(3): transformPlaneToWorldMatrixVtk.SetElement( rowIndex, colIndex, transformPlaneToWorldMatrix[rowIndex, colIndex]) transformPlaneToWorld.SetMatrix(transformPlaneToWorldMatrixVtk) polyTransformToWorld = vtk.vtkTransformPolyDataFilter() polyTransformToWorld.SetTransform(transformPlaneToWorld) polyTransformToWorld.SetInputConnection(triangulator.GetOutputPort()) polyTransformToWorld.Update() clippingPolyData = polyTransformToWorld.GetOutput() self.roiModelNode.SetAndObservePolyData(clippingPolyData) self.roiModelNode.Modified()
# This module was tested on 3D Slicer version 4.3.1
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 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 PolyDataToImageData(self, inputPolydata_Ras, referenceVolumeNode_Ras, inVal=100, outVal=0): """ We take in an polydata and convert it to an new image data , withing the Reference Voulume node the reference volume node is cleared with a threshold because originally the volume may contain alot of noisy pixels PARAM: inputPolydata_Ras: Polydata we are looking to conver vtkPolydata() PARAM: refernceVolumeNode_Ras vtkMRMLScalarVolumeNode() RETURN : vtkImageData """ """ Transform the polydata from ras to ijk using the referenceVolumeNode """ #inputPolydataTriangulated_Ijk=polyToImage.GetOutput() transformPolydataFilter=vtk.vtkTransformPolyDataFilter() rasToIjkMatrix=vtk.vtkMatrix4x4() referenceVolumeNode_Ras.GetRASToIJKMatrix(rasToIjkMatrix) rasToIjkTransform = vtk.vtkTransform() rasToIjkTransform.SetMatrix(rasToIjkMatrix) transformPolydataFilter.SetTransform(rasToIjkTransform) transformPolydataFilter.SetInputData(inputPolydata_Ras) transformPolydataFilter.Update() inputPolydata_Ijk=transformPolydataFilter.GetOutput() normalsFunction=vtk.vtkPolyDataNormals() normalsFunction.SetInputData(inputPolydata_Ijk) normalsFunction.ConsistencyOn() trigFilter=vtk.vtkTriangleFilter() trigFilter.SetInputConnection(normalsFunction.GetOutputPort()) stripper=vtk.vtkStripper() stripper.SetInputConnection(trigFilter.GetOutputPort()) stripper.Update() inputPolydataTriangulated_Ijk=stripper.GetOutput() # Clone reference image and clear it referenceImage_Ijk = referenceVolumeNode_Ras.GetImageData() # Fill image with outVal (there is no volume Fill filter in VTK, therefore we need to use threshold filter) thresh = vtk.vtkImageThreshold() thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.SetInValue(outVal) thresh.SetOutValue(outVal) #thresh.SetOutputScalarType (vtk.VTK_UNSIGNED_CHAR) thresh.SetInputData(referenceImage_Ijk) thresh.Update() whiteImage_Ijk = thresh.GetOutput() # Convert polydata to stencil polyToImage = vtk.vtkPolyDataToImageStencil() polyToImage.SetInputData(inputPolydataTriangulated_Ijk) polyToImage.SetOutputSpacing(whiteImage_Ijk.GetSpacing()) polyToImage.SetOutputOrigin(whiteImage_Ijk.GetOrigin()) polyToImage.SetOutputWholeExtent(whiteImage_Ijk.GetExtent()) polyToImage.Update() imageStencil_Ijk=polyToImage.GetOutput() # Convert stencil to image imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(whiteImage_Ijk) imgstenc.SetStencilData(imageStencil_Ijk) imgstenc.ReverseStencilOn() imgstenc.SetBackgroundValue(inVal) imgstenc.Update() return imgstenc.GetOutput()
def PolyDataToImageData(self, inputPolydata_Ras, referenceVolumeNode_Ras, inVal=100, outVal=0): """ We take in an polydata and convert it to an new image data , withing the Reference Voulume node the reference volume node is cleared with a threshold because originally the volume may contain alot of noisy pixels PARAM: inputPolydata_Ras: Polydata we are looking to conver vtkPolydata() PARAM: refernceVolumeNode_Ras vtkMRMLScalarVolumeNode() RETURN : vtkImageData """ """ Transform the polydata from ras to ijk using the referenceVolumeNode """ #inputPolydataTriangulated_Ijk=polyToImage.GetOutput() transformPolydataFilter = vtk.vtkTransformPolyDataFilter() rasToIjkMatrix = vtk.vtkMatrix4x4() referenceVolumeNode_Ras.GetRASToIJKMatrix(rasToIjkMatrix) rasToIjkTransform = vtk.vtkTransform() rasToIjkTransform.SetMatrix(rasToIjkMatrix) transformPolydataFilter.SetTransform(rasToIjkTransform) transformPolydataFilter.SetInputData(inputPolydata_Ras) transformPolydataFilter.Update() inputPolydata_Ijk = transformPolydataFilter.GetOutput() normalsFunction = vtk.vtkPolyDataNormals() normalsFunction.SetInputData(inputPolydata_Ijk) normalsFunction.ConsistencyOn() trigFilter = vtk.vtkTriangleFilter() trigFilter.SetInputConnection(normalsFunction.GetOutputPort()) stripper = vtk.vtkStripper() stripper.SetInputConnection(trigFilter.GetOutputPort()) stripper.Update() inputPolydataTriangulated_Ijk = stripper.GetOutput() # Clone reference image and clear it referenceImage_Ijk = referenceVolumeNode_Ras.GetImageData() # Fill image with outVal (there is no volume Fill filter in VTK, therefore we need to use threshold filter) thresh = vtk.vtkImageThreshold() thresh.ReplaceInOn() thresh.ReplaceOutOn() thresh.SetInValue(outVal) thresh.SetOutValue(outVal) #thresh.SetOutputScalarType (vtk.VTK_UNSIGNED_CHAR) thresh.SetInputData(referenceImage_Ijk) thresh.Update() whiteImage_Ijk = thresh.GetOutput() # Convert polydata to stencil polyToImage = vtk.vtkPolyDataToImageStencil() polyToImage.SetInputData(inputPolydataTriangulated_Ijk) polyToImage.SetOutputSpacing(whiteImage_Ijk.GetSpacing()) polyToImage.SetOutputOrigin(whiteImage_Ijk.GetOrigin()) polyToImage.SetOutputWholeExtent(whiteImage_Ijk.GetExtent()) polyToImage.Update() imageStencil_Ijk = polyToImage.GetOutput() # Convert stencil to image imgstenc = vtk.vtkImageStencil() imgstenc.SetInputData(whiteImage_Ijk) imgstenc.SetStencilData(imageStencil_Ijk) imgstenc.ReverseStencilOn() imgstenc.SetBackgroundValue(inVal) imgstenc.Update() return imgstenc.GetOutput()
def vtk_to_obj_converter(self, node, radius=0.1, number_of_sides=3): qt.QApplication.setOverrideCursor(qt.Qt.WaitCursor) polydata = node.GetPolyData() tuber = vtk.vtkTubeFilter() tuber.SetNumberOfSides(int(number_of_sides)) tuber.SetRadius(radius) tuber.SetInputData(polydata) tuber.Update() tubes = tuber.GetOutputDataObject(0) # scalars = tubes.GetPointData().GetArray(0) # scalars.SetName("scalars") triangles = vtk.vtkTriangleFilter() triangles.SetInputData(tubes) triangles.Update() tripolydata = vtk.vtkPolyData() tripolydata.ShallowCopy(triangles.GetOutput()) # Decrease the number of triangle of 30% to reduce Blender loading costs decimate = vtk.vtkDecimatePro() decimate.SetInputData(tripolydata) decimate.SetTargetReduction(.30) decimate.Update() mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(decimate.GetOutputPort()) r = random.randrange(0, 256, 1) g = random.randrange(0, 256, 1) b = random.randrange(0, 256, 1) actor = vtk.vtkActor() actor.SetMapper(mapper) # actor.GetProperty().SetColor(0, 0, 0) # Ka: ambient color of the material (r, g, b) actor.GetProperty().SetDiffuseColor( r, g, b) # Kd: diffuse color of the material (r, g, b) # actor.GetProperty().SetSpecularColor(0, 0, 0) # Ks: specular color of the material (r, g, b) renderer = vtk.vtkRenderer() renderer.AddActor(actor) window = vtk.vtkRenderWindow() window.AddRenderer(renderer) # Get output path storageNode = node.GetStorageNode() filepath = storageNode.GetFullNameFromFileName() filename = filepath.rsplit('.', 1) writer = vtk.vtkOBJExporter() writer.SetFilePrefix(filename[0]) writer.SetInput(window) writer.Write() qt.QApplication.restoreOverrideCursor() if writer.Write() == 0: qt.QMessageBox.critical(None, "Conversion", "Conversion failed") else: qt.QMessageBox.information(None, "Conversion", "Conversion done")
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