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 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 ClipData(self, ROI, noisySurfacePolyData): """ Returns the clipped polydata from the region defined by the ROI Turn on the Debug to make the clipped object appear, For specific filter functionality see DataFlow doc: ClipData.pdf """ connectivityFilter = vtk.vtkPolyDataConnectivityFilter() self.utility.PolyDataWriter( noisySurfacePolyData, "C:\\MakeHDRApplicatorMask\\doc\\" + "DebugPolyData\\PreClipped.vtk" ) connectivityFilter.SetInputData(noisySurfacePolyData) connectivityFilter.SetExtractionModeToLargestRegion() connectivityFilter.Update() self.skinSurface = connectivityFilter.GetOutput() # skinSurface Set if self.DEBUG_CONNECTIVITYFACE: self.utility.DisplayPolyData("ConnectedFace", self.skinSurface) # Expansion of ROI is explained in vtkImplicitModeller limitations ROIExtents = self.utility.GetROIExtents(ROI) BiggerROI = self.utility.ExpandExtents(ROIExtents, 0.5) # See vtkImplicitModdeler limitations.pdf for explanation implicitBoxRegion = vtk.vtkBox() implicitBoxRegion.SetBounds(BiggerROI) clipper = vtk.vtkClipPolyData() clipper.InsideOutOn() # Clip the regions outside of implicit function clipper.SetInputConnection(connectivityFilter.GetOutputPort()) clipper.SetClipFunction(implicitBoxRegion) clipper.Update() self.clippedSurface = clipper.GetOutput() return clipper
def ClipData(self, ROI, noisySurfacePolyData): """ Returns the clipped polydata from the region defined by the ROI Turn on the Debug to make the clipped object appear, For specific filter functionality see DataFlow doc: ClipData.pdf """ connectivityFilter = vtk.vtkPolyDataConnectivityFilter() self.utility.PolyDataWriter(noisySurfacePolyData, "C:\\MakeHDRApplicatorMask\\doc\\"+\ "DebugPolyData\\PreClipped.vtk") connectivityFilter.SetInputData(noisySurfacePolyData) connectivityFilter.SetExtractionModeToLargestRegion() connectivityFilter.Update() self.skinSurface = connectivityFilter.GetOutput() #skinSurface Set if self.DEBUG_CONNECTIVITYFACE: self.utility.DisplayPolyData("ConnectedFace", self.skinSurface) # Expansion of ROI is explained in vtkImplicitModeller limitations ROIExtents = self.utility.GetROIExtents(ROI) BiggerROI = self.utility.ExpandExtents(ROIExtents, .5) #See vtkImplicitModdeler limitations.pdf for explanation implicitBoxRegion = vtk.vtkBox() implicitBoxRegion.SetBounds(BiggerROI) clipper = vtk.vtkClipPolyData() clipper.InsideOutOn() # Clip the regions outside of implicit function clipper.SetInputConnection(connectivityFilter.GetOutputPort()) clipper.SetClipFunction(implicitBoxRegion) clipper.Update() self.clippedSurface = clipper.GetOutput() return clipper
def getAverageNormalFromModelPoint(model, point): normalsOfModel = slicer.util.arrayFromModelPointData(model, 'Normals') modelMesh = model.GetMesh() pointID = modelMesh.FindPoint(point) normalAtPointID = normalsOfModel[pointID] cylinder = vtk.vtkCylinder() cylinder.SetRadius(3) cylinder.SetCenter(point) cylinder.SetAxis(normalAtPointID) clipper = vtk.vtkClipPolyData() clipper.SetInputData(model.GetPolyData()) clipper.InsideOutOn() clipper.SetClipFunction(cylinder) clipper.Update() connectivityFilter = vtk.vtkConnectivityFilter() connectivityFilter.SetInputData(clipper.GetOutput()) connectivityFilter.SetClosestPoint(point) connectivityFilter.SetExtractionModeToClosestPointRegion() connectivityFilter.Update() cylinderIntersectionModel = slicer.mrmlScene.AddNewNodeByClass( 'vtkMRMLModelNode', 'cylinderIntersection') cylinderIntersectionModel.CreateDefaultDisplayNodes() cylinderIntersectionModel.SetAndObservePolyData( connectivityFilter.GetOutput()) averageNormal = getAverageNormalFromModel(cylinderIntersectionModel) slicer.mrmlScene.RemoveNode(cylinderIntersectionModel) return averageNormal
def MinimumDistanceMask(self, vtkAlgorythmObject, distanceFromMask, ROI, ruler, isBubble=False): """ Takes an algorythm object which is will send through a pipeline to create a mask defining the minimum distance value from the skin surface returns an algorythm object as well to preform GetOutput() -> polydata or GetOutputPort() -> algorythm see MinimumDistanceMask.pdf """ if distanceFromMask < 2: print "WARNING: MouldLogic: MinimumDistanceMask implicit", "modeling is very unstable below 1.5 , mask may degrade", "and lines will become discontinuous." Extents = self.utility.GetROIExtents(ROI) if (isBubble): Extents = self.utility.ExpandExtents(Extents, 100) implicitModeller = vtk.vtkImplicitModeller() implicitModeller.SetInputConnection(vtkAlgorythmObject.GetOutputPort()) implicitModeller.SetMaximumDistance(distanceFromMask) implicitModeller.SetModelBounds(Extents) implicitModeller.AdjustBoundsOn() implicitModeller.SetAdjustBounds(10) # Removes the boundary effects implicitModeller.CappingOff( ) # Important to create disjoint inner and outer masks implicitModeller.SetProcessModeToPerVoxel() implicitModeller.Update() contourFilter = vtk.vtkContourFilter() contourFilter.SetValue(0, distanceFromMask) contourFilter.SetInputConnection(implicitModeller.GetOutputPort()) contourFilter.Update() normalsFunction = vtk.vtkPolyDataNormals() normalsFunction.FlipNormalsOn() normalsFunction.AddInputConnection(contourFilter.GetOutputPort()) normalsFunction.Update() implicitBoxRegion = vtk.vtkBox() implicitBoxRegion.SetBounds(Extents) clipper2 = vtk.vtkClipPolyData() clipper2.InsideOutOn() # Clip the regions outside of implicit function clipper2.SetInputConnection(normalsFunction.GetOutputPort()) clipper2.SetClipFunction(implicitBoxRegion) clipper2.Update() closestPoint = [0, 0, 0] ruler.GetPosition1(closestPoint) connectivityFilter = vtk.vtkPolyDataConnectivityFilter() connectivityFilter.SetInputConnection(clipper2.GetOutputPort()) connectivityFilter.SetExtractionModeToClosestPointRegion() connectivityFilter.SetClosestPoint(closestPoint) connectivityFilter.Update() return connectivityFilter.GetOutput()
def getIntersectionBetweenModelAnd1PlaneWithNormalAndOrigin( modelNode, normal, origin, intersectionModel): plane = vtk.vtkPlane() plane.SetOrigin(origin) plane.SetNormal(normal) clipper = vtk.vtkClipPolyData() clipper.SetInputData(modelNode.GetPolyData()) clipper.SetClipFunction(plane) clipper.Update() intersectionModel.SetAndObservePolyData(clipper.GetOutput())
def MinimumDistanceMask(self, vtkAlgorythmObject, distanceFromMask, ROI, ruler, isBubble=False): """ Takes an algorythm object which is will send through a pipeline to create a mask defining the minimum distance value from the skin surface returns an algorythm object as well to preform GetOutput() -> polydata or GetOutputPort() -> algorythm see MinimumDistanceMask.pdf """ if distanceFromMask < 2: print "WARNING: MouldLogic: MinimumDistanceMask implicit", "modeling is very unstable below 1.5 , mask may degrade", "and lines will become discontinuous." Extents = self.utility.GetROIExtents(ROI) if isBubble: Extents = self.utility.ExpandExtents(Extents, 100) implicitModeller = vtk.vtkImplicitModeller() implicitModeller.SetInputConnection(vtkAlgorythmObject.GetOutputPort()) implicitModeller.SetMaximumDistance(distanceFromMask) implicitModeller.SetModelBounds(Extents) implicitModeller.AdjustBoundsOn() implicitModeller.SetAdjustBounds(10) # Removes the boundary effects implicitModeller.CappingOff() # Important to create disjoint inner and outer masks implicitModeller.SetProcessModeToPerVoxel() implicitModeller.Update() contourFilter = vtk.vtkContourFilter() contourFilter.SetValue(0, distanceFromMask) contourFilter.SetInputConnection(implicitModeller.GetOutputPort()) contourFilter.Update() normalsFunction = vtk.vtkPolyDataNormals() normalsFunction.FlipNormalsOn() normalsFunction.AddInputConnection(contourFilter.GetOutputPort()) normalsFunction.Update() implicitBoxRegion = vtk.vtkBox() implicitBoxRegion.SetBounds(Extents) clipper2 = vtk.vtkClipPolyData() clipper2.InsideOutOn() # Clip the regions outside of implicit function clipper2.SetInputConnection(normalsFunction.GetOutputPort()) clipper2.SetClipFunction(implicitBoxRegion) clipper2.Update() closestPoint = [0, 0, 0] ruler.GetPosition1(closestPoint) connectivityFilter = vtk.vtkPolyDataConnectivityFilter() connectivityFilter.SetInputConnection(clipper2.GetOutputPort()) connectivityFilter.SetExtractionModeToClosestPointRegion() connectivityFilter.SetClosestPoint(closestPoint) connectivityFilter.Update() return connectivityFilter.GetOutput()
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, 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