def ComputeMeanDistance(self, inputSourceModel, inputTargetModel, transform ): sourcePolyData = inputSourceModel.GetPolyData() targetPolyData = inputTargetModel.GetPolyData() cellId = vtk.mutable(0) subId = vtk.mutable(0) dist2 = vtk.mutable(0.0) locator = vtk.vtkCellLocator() locator.SetDataSet( targetPolyData ) locator.SetNumberOfCellsPerBucket( 1 ) locator.BuildLocator() totalDistance = 0.0 sourcePoints = sourcePolyData.GetPoints() n = sourcePoints.GetNumberOfPoints() m = vtk.vtkMath() for sourcePointIndex in xrange(n): sourcePointPos = [0, 0, 0] sourcePoints.GetPoint( sourcePointIndex, sourcePointPos ) transformedSourcePointPos = [0, 0, 0, 1] #transform.GetTransformToParent().TransformVector( sourcePointPos, transformedSourcePointPos ) sourcePointPos.append(1) transform.GetTransformToParent().MultiplyPoint( sourcePointPos, transformedSourcePointPos ) #transformedPoints.InsertNextPoint( transformedSourcePointPos ) surfacePoint = [0, 0, 0] transformedSourcePointPos.pop() locator.FindClosestPoint( transformedSourcePointPos, surfacePoint, cellId, subId, dist2 ) totalDistance = totalDistance + math.sqrt(dist2) return ( totalDistance / n )
def ComputeMeanDistance(self, inputSourceModel, inputTargetModel, transform ): sourcePolyData = inputSourceModel.GetPolyData() targetPolyData = inputTargetModel.GetPolyData() cellId = vtk.mutable(0) subId = vtk.mutable(0) dist2 = vtk.mutable(0.0) locator = vtk.vtkCellLocator() locator.SetDataSet( targetPolyData ) locator.SetNumberOfCellsPerBucket( 1 ) locator.BuildLocator() totalDistance = 0.0 sourcePoints = sourcePolyData.GetPoints() n = sourcePoints.GetNumberOfPoints() m = vtk.vtkMath() for sourcePointIndex in range(n): sourcePointPos = [0, 0, 0] sourcePoints.GetPoint( sourcePointIndex, sourcePointPos ) transformedSourcePointPos = [0, 0, 0, 1] #transform.GetTransformToParent().TransformVector( sourcePointPos, transformedSourcePointPos ) sourcePointPos.append(1) transform.GetTransformToParent().MultiplyPoint( sourcePointPos, transformedSourcePointPos ) #transformedPoints.InsertNextPoint( transformedSourcePointPos ) surfacePoint = [0, 0, 0] transformedSourcePointPos.pop() locator.FindClosestPoint( transformedSourcePointPos, surfacePoint, cellId, subId, dist2 ) totalDistance = totalDistance + math.sqrt(dist2) return ( totalDistance / n )
def computeCameraUpDirectionInRAS(self, toolCameraToRASTransform, cameraOriginInRASMm, focalPointInRASMm): upDirectionInRAS = [0,0,0] # placeholder values if (self.forcedUpDirection == True): math = vtk.vtkMath() # cross product of forwardDirectionInRAS vector with upInRAS vector is the rightDirectionInRAS vector upInRAS = self.upInRAS forwardDirectionInRAS = self.computeCameraProjectionDirectionInRAS(cameraOriginInRASMm, focalPointInRASMm) rightDirectionInRAS = [0,0,0] # placeholder values math.Cross(forwardDirectionInRAS,upInRAS,rightDirectionInRAS) numberDimensions = 3; lengthMm = math.Norm(rightDirectionInRAS,numberDimensions) epsilon = 0.0001 if (lengthMm < epsilon): # must check for this case logging.warning("Warning: length of cross product in computeCameraUpDirectionInRAS is zero. Workaround used") backupUpDirectionInRAS = [1,1,1] # if the previous cross product was zero, then this shouldn't be math.Normalize(backupUpDirectionInRAS) upInRAS = backupUpDirectionInRAS math.Cross(forwardDirectionInRAS,upInRAS,rightDirectionInRAS) math.Normalize(rightDirectionInRAS) # now compute the cross product between the rightDirectionInRAS and forwardDirectionInRAS directions to get a corrected up vector upDirectionInRAS = [0,0,0] # placeholder values math.Cross(rightDirectionInRAS,forwardDirectionInRAS,upDirectionInRAS) math.Normalize(upDirectionInRAS) else: upDirectionInToolCamera = [0,1,0] # standard up direction in OpenGL dummyPoint = [0,0,0] # Needed by the TransformVectorAtPoint function toolCameraToRASTransform.TransformVectorAtPoint(dummyPoint,upDirectionInToolCamera,upDirectionInRAS) return upDirectionInRAS
def ComputeMeanDistance(self, inputFiducials, inputModel, transform): surfacePoints = vtk.vtkPoints() cellId = vtk.mutable(0) subId = vtk.mutable(0) dist2 = vtk.mutable(0.0) locator = vtk.vtkCellLocator() locator.SetDataSet(inputModel.GetPolyData()) locator.SetNumberOfCellsPerBucket(1) locator.BuildLocator() totalDistance = 0.0 n = inputFiducials.GetNumberOfFiducials() m = vtk.vtkMath() for fiducialIndex in range(0, n): originalPoint = [0, 0, 0] inputFiducials.GetNthFiducialPosition(fiducialIndex, originalPoint) transformedPoint = [0, 0, 0, 1] #transform.GetTransformToParent().TransformVector(originalPoint, transformedPoint) originalPoint.append(1) transform.GetTransformToParent().MultiplyPoint(originalPoint, transformedPoint) #transformedPoints.InsertNextPoint(transformedPoint) surfacePoint = [0, 0, 0] transformedPoint.pop() locator.FindClosestPoint(transformedPoint, surfacePoint, cellId, subId, dist2) totalDistance = totalDistance + math.sqrt(dist2) return (totalDistance / n)
def ComputeMeanDistance(self, inputFiducials, inputModel, transform ): surfacePoints = vtk.vtkPoints() cellId = vtk.mutable(0) subId = vtk.mutable(0) dist2 = vtk.mutable(0.0) locator = vtk.vtkCellLocator() locator.SetDataSet( inputModel.GetPolyData() ) locator.SetNumberOfCellsPerBucket( 1 ) locator.BuildLocator() totalDistance = 0.0 n = inputFiducials.GetNumberOfFiducials() m = vtk.vtkMath() for fiducialIndex in range( 0, n ): originalPoint = [0, 0, 0] inputFiducials.GetNthFiducialPosition( fiducialIndex, originalPoint ) transformedPoint = [0, 0, 0, 1] #transform.GetTransformToParent().TransformVector( originalPoint, transformedPoint ) originalPoint.append(1) transform.GetTransformToParent().MultiplyPoint( originalPoint, transformedPoint ) #transformedPoints.InsertNextPoint( transformedPoint ) surfacePoint = [0, 0, 0] transformedPoint.pop() locator.FindClosestPoint( transformedPoint, surfacePoint, cellId, subId, dist2 ) totalDistance = totalDistance + math.sqrt(dist2) return ( totalDistance / n )
def updateSlice(self, point, angle): print self.polydataPoints if self.polydataPoints: pos = self.polydataPoints.GetPoint(point) norm = [0.0, 0.0, 0.0] v1 = [0.0, 0.0, 0.0] v2 = [0.0, 0.0, 0.0] if point < self.numberOfPoints-1: pos1 = self.polydataPoints.GetPoint(point+1) norm = [pos1[0]-pos[0], pos1[1]-pos[1], pos1[2]-pos[2]] else: pos1 = self.polydataPoints.GetPoint(point-1) norm = [-(pos1[0]-pos[0]), -(pos1[1]-pos[1]), -(pos1[2]-pos[2])] math = vtk.vtkMath() normLength = math.Normalize(norm) norm[0] /= normLength norm[1] /= normLength norm[2] /= normLength math.Perpendiculars(norm,v1,v2,angle*math.Pi()/180) self.redViewer.SetSliceToRASByNTP(norm[0],norm[1],norm[2],v1[0],v1[1],v1[2],pos[0],pos[1],pos[2],0)
def getClustersCenterOfMass(self,fiducialList,sortClusters=False): clusterMassCenter = {} sortedClusterMassCenter = {} clusterFiducials = {} fiducialPosition = [0.0, 0.0, 0.0] clusterPointPosition = [0.0, 0.0, 0.0] mathDist = vtk.vtkMath() distanceThreshold = 40 for pt in range(fiducialList.GetNumberOfFiducials()): belongToExistingCluster = False fiducialList.GetNthFiducialPosition(pt,fiducialPosition) # Compute distance from fiducial to the first point of all clusters for cluster in range(len(clusterFiducials)): fiducialList.GetNthFiducialPosition(clusterFiducials[cluster][0],clusterPointPosition) dist = math.sqrt(mathDist.Distance2BetweenPoints(clusterPointPosition,fiducialPosition)) # Fiducial belong to current cluster. Add it to the list of point of the current cluster. if dist < distanceThreshold: clusterFiducials[cluster].append(pt); belongToExistingCluster = True break # Fiducial does not belong to any cluster. Create a new one. if not belongToExistingCluster: clusterFiducials[len(clusterFiducials)] = [pt] # Compute center of mass of each cluster for cluster in range(len(clusterFiducials)): centerOfMass = [0.0, 0.0, 0.0] for pts in range(len(clusterFiducials[cluster])): tmpPos = [0.0, 0.0, 0.0] fiducialList.GetNthFiducialPosition(clusterFiducials[cluster][pts],tmpPos) centerOfMass[0] = centerOfMass[0] + tmpPos[0] centerOfMass[1] = centerOfMass[1] + tmpPos[1] centerOfMass[2] = centerOfMass[2] + tmpPos[2] centerOfMass[0] = centerOfMass[0] / len(clusterFiducials[cluster]) centerOfMass[1] = centerOfMass[1] / len(clusterFiducials[cluster]) centerOfMass[2] = centerOfMass[2] / len(clusterFiducials[cluster]) clusterMassCenter[cluster] = [centerOfMass[0], centerOfMass[1], centerOfMass[2]] # Order cluster list by number of fiducials in it if sortClusters: sortedClusters = sorted(clusterFiducials, key=lambda i: int(len(clusterFiducials[i]))) for cluster in range(len(clusterMassCenter)): sortedClusterMassCenter[cluster] = [clusterMassCenter[sortedClusters[cluster]][0], clusterMassCenter[sortedClusters[cluster]][1], clusterMassCenter[sortedClusters[cluster]][2]] return sortedClusterMassCenter return clusterMassCenter
def computeCameraProjectionDirectionInRAS(self, cameraOriginInRASMm, focalPointInRASMm): math = vtk.vtkMath() directionFromOriginToFocalPointRAS = [0,0,0] # placeholder values math.Subtract(focalPointInRASMm,cameraOriginInRASMm,directionFromOriginToFocalPointRAS) math.Normalize(directionFromOriginToFocalPointRAS) numberDimensions = 3; lengthMm = math.Norm(directionFromOriginToFocalPointRAS,numberDimensions) epsilon = 0.0001 if (lengthMm < epsilon): logging.warning("Warning: computeCameraProjectionDirectionInRAS() is computing a zero vector. Check target model? Using [0,0,-1] as target direction.") directionFromOriginToFocalPointRAS = [0,0,-1]; return directionFromOriginToFocalPointRAS
def __init__(self, entryPointFiducialListNode, targetFiducialListNode, shape, shapeRadius, shapeHeight, shapeVolume, ablationZoneColor): entryPointFid = entryPointFiducialListNode targetFid = targetFiducialListNode scene = slicer.mrmlScene if (shape == 'sphere'): source = vtk.vtkSphereSource() source.SetRadius(shapeRadius) source.Update() elif (shape == 'cylinder'): source = vtk.vtkCylinderSource() source.SetRadius(shapeRadius) source.SetHeight(shapeHeight) source.Update() elif (shape == 'ellipsoid'): source = vtk.vtkSphereSource() source.SetRadius(shapeRadius) source.Update() else: source = vtk.vtkSphereSource() source.SetRadius(shapeRadius) source.Update() # get coordinates from current entry point fiducial currentEntryPointFiducialCoordinatesRAS = [0, 0, 0] entryPointFid.GetFiducialCoordinates(currentEntryPointFiducialCoordinatesRAS) currentTargetFiducialCoordinatesRAS = [0, 0, 0] targetFid.GetFiducialCoordinates(currentTargetFiducialCoordinatesRAS) translationTarget = [currentTargetFiducialCoordinatesRAS[0], currentTargetFiducialCoordinatesRAS[1], currentTargetFiducialCoordinatesRAS[2]] # Generate a random start and end point random.seed(8775070) startPoint = [0 for i in range(3)] startPoint[0] = currentEntryPointFiducialCoordinatesRAS[0] startPoint[1] = currentEntryPointFiducialCoordinatesRAS[1] startPoint[2] = currentEntryPointFiducialCoordinatesRAS[2] endPoint = [0 for i in range(3)] endPoint[0] = currentTargetFiducialCoordinatesRAS[0] endPoint[1] = currentTargetFiducialCoordinatesRAS[1] endPoint[2] = currentTargetFiducialCoordinatesRAS[2] # Compute a basis normalizedX = [0 for i in range(3)] normalizedY = [0 for i in range(3)] normalizedZ = [0 for i in range(3)] # The X axis is a vector from start to end math = vtk.vtkMath() math.Subtract(endPoint, startPoint, normalizedX) # length = math.Norm(normalizedX) math.Normalize(normalizedX) # The Z axis is an arbitrary vector cross X arbitrary = [0 for i in range(3)] arbitrary[0] = random.uniform(-10,10) arbitrary[1] = random.uniform(-10,10) arbitrary[2] = random.uniform(-10,10) math.Cross(normalizedX, arbitrary, normalizedZ) math.Normalize(normalizedZ) # The Y axis is Z cross X math.Cross(normalizedZ, normalizedX, normalizedY) matrix = vtk.vtkMatrix4x4() # Create the direction cosine matrix matrix.Identity() for i in range(3): matrix.SetElement(i, 0, normalizedX[i]) matrix.SetElement(i, 1, normalizedY[i]) matrix.SetElement(i, 2, normalizedZ[i]) matrix.SetElement(i, 3, currentTargetFiducialCoordinatesRAS[i]) # Apply the transforms transform = vtk.vtkTransform() transform.Concatenate(matrix) transform.RotateZ(90) ''' ps = vtk.vtkProgrammableSource() import math numPts = 80 polyLinePoints = vtk.vtkPoints() polyLinePoints.SetNumberOfPoints(numPts) R=1.0 for i in range(0,numPts): x = R*math.cos(i*2*math.pi/numPts) y = R*math.sin(i*2*math.pi/numPts) polyLinePoints.InsertPoint(i, x, y, 0) aPolyLine1 = vtk.vtkPolyLine() aPolyLine1.GetPointIds().SetNumberOfIds(numPts+1) for i in range(0,numPts): aPolyLine1.GetPointIds().SetId(i,i) # add one more cell at the end to close the circle on itself aPolyLine1.GetPointIds().SetId(numPts, 0) aPolyLineGrid = ps.GetOutput() aPolyLineGrid.Allocate(1,1) aPolyLineGrid.InsertNextCell(aPolyLine1.GetCellType(), aPolyLine1.GetPointIds()) aPolyLineGrid.SetPoints(polyLinePoints) ''' ''' #This script generates a helix double. #This is intended as the script of a 'Programmable Source' import math ps = vtk.vtkSphereSource() numPts = 80 # Points along each Helix length = 8 # Length of each Helix rounds = 3 # Number of times around phase_shift = math.pi/1.5 # Phase shift between Helixes #Get a vtk.PolyData object for the output pdo = ps.GetOutput() print "before" print pdo #This will store the points for the Helix newPts = vtk.vtkPoints() for i in range(0, numPts): #Generate Points for first Helix x = i*length/numPts y = math.sin(i*rounds*2*math.pi/numPts) z = math.cos(i*rounds*2*math.pi/numPts) newPts.InsertPoint(i, x,y,z) #Generate Points for second Helix. Add a phase offset to y and z. y = math.sin(i*rounds*2*math.pi/numPts+phase_shift) z = math.cos(i*rounds*2*math.pi/numPts+phase_shift) #Offset Helix 2 pts by 'numPts' to keep separate from Helix 1 Pts newPts.InsertPoint(i+numPts, x,y,z) #Add the points to the vtkPolyData object pdo.SetPoints(newPts) #Make two vtkPolyLine objects to hold curve construction data aPolyLine1 = vtk.vtkPolyLine() aPolyLine2 = vtk.vtkPolyLine() #Indicate the number of points along the line aPolyLine1.GetPointIds().SetNumberOfIds(numPts) aPolyLine2.GetPointIds().SetNumberOfIds(numPts) for i in range(0,numPts): #First Helix - use the first set of points aPolyLine1.GetPointIds().SetId(i, i) #Second Helix - use the second set of points #(Offset the point reference by 'numPts'). aPolyLine2.GetPointIds().SetId(i,i+numPts) #Allocate the number of 'cells' that will be added. #Two 'cells' for the Helix curves, and one 'cell' #for every 3rd point along the Helixes. links = range(0,numPts,3) pdo.Allocate(2+len(links), 1) #Add the poly line 'cell' to the vtkPolyData object. pdo.InsertNextCell(aPolyLine1.GetCellType(), aPolyLine1.GetPointIds()) pdo.InsertNextCell(aPolyLine2.GetCellType(), aPolyLine2.GetPointIds()) for i in links: #Add a line connecting the two Helixes. aLine = vtk.vtkLine() aLine.GetPointIds().SetId(0, i) aLine.GetPointIds().SetId(1, i+numPts) pdo.InsertNextCell(aLine.GetCellType(), aLine.GetPointIds()) print "after" print pdo ''' # Create model node lesionModel = slicer.vtkMRMLModelNode() lesionModel.SetScene(scene) lesionModel.SetName("Ablationzone-%s" % targetFid.GetName()) lesionModel.SetAndObservePolyData(source.GetOutput()) self.lesionModel = lesionModel # Create display node lesionModelDisplay = slicer.vtkMRMLModelDisplayNode() lesionModelDisplay.SetColor(ablationZoneColor) lesionModelDisplay.SetOpacity(0.4) lesionModelDisplay.SliceIntersectionVisibilityOn() lesionModelDisplay.SetScene(scene) scene.AddNode(lesionModelDisplay) lesionModel.SetAndObserveDisplayNodeID(lesionModelDisplay.GetID()) # Add to scene lesionModelDisplay.SetPolyData(source.GetOutput()) self.lesionModelDisplay = lesionModelDisplay self.lesionModel= lesionModel scene.AddNode(lesionModel) # Create ablationZoneTransform node ablationZoneTransform = slicer.vtkMRMLLinearTransformNode() ablationZoneTransform.SetName('AblationZoneTransform-%s' % targetFid.GetName()) scene.AddNode(ablationZoneTransform) ablationZoneTransform.ApplyTransformMatrix(transform.GetMatrix()) lesionModel.SetAndObserveTransformNodeID(ablationZoneTransform.GetID()) self.ablationZoneTransform = ablationZoneTransform
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 calculatePerpendicularVectors(self, initialVector, v1, v2): vtkmath = vtk.vtkMath() tmpZvector = [0.0, 0.0, 1.0] vtkmath.Cross(initialVector, tmpZvector, v1) vtkmath.Cross(initialVector, v1, v2)
def __init__(self, entryPointFiducialListNode, targetFiducialListNode, length, diameter, probeText, probeColor): entryPointFid = entryPointFiducialListNode targetFid = targetFiducialListNode scene = slicer.mrmlScene #Create an probe. probe = vtk.vtkCylinderSource() probe.SetHeight(length) probe.SetRadius(diameter / 2) pos = [0 for i in range(3)] # get coordinates from current entry point fiducial currentEntryPointFiducialCoordinatesRAS = [0, 0, 0] entryPointFid.GetFiducialCoordinates(currentEntryPointFiducialCoordinatesRAS) currentTargetFiducialCoordinatesRAS = [0, 0, 0] targetFid.GetFiducialCoordinates(currentTargetFiducialCoordinatesRAS) # pos is the vector that describes the distance between the target and the entry point for i in range(3): pos[i] = currentTargetFiducialCoordinatesRAS[i] - currentEntryPointFiducialCoordinatesRAS[i] pointsDistance = sqrt(pow(pos[0], 2) + pow(pos[1], 2) + pow(pos[2], 2)) # len is the vector that describes the length of the probe len = [0 for i in range(3)] for i in range(3): len[i] = length / pointsDistance * pos[i] translationTarget = [currentTargetFiducialCoordinatesRAS[0] - len[0] / 2, currentTargetFiducialCoordinatesRAS[1] - len[1] / 2, currentTargetFiducialCoordinatesRAS[2] - len[2] / 2] # Generate a random start and end point random.seed(8775070) startPoint = [0 for i in range(3)] startPoint[0] = currentEntryPointFiducialCoordinatesRAS[0] startPoint[1] = currentEntryPointFiducialCoordinatesRAS[1] startPoint[2] = currentEntryPointFiducialCoordinatesRAS[2] endPoint = [0 for i in range(3)] endPoint[0] = currentTargetFiducialCoordinatesRAS[0] endPoint[1] = currentTargetFiducialCoordinatesRAS[1] endPoint[2] = currentTargetFiducialCoordinatesRAS[2] # Compute a basis normalizedX = [0 for i in range(3)] normalizedY = [0 for i in range(3)] normalizedZ = [0 for i in range(3)] # The X axis is a vector from start to end math = vtk.vtkMath() math.Subtract(endPoint, startPoint, normalizedX) # length = math.Norm(normalizedX) math.Normalize(normalizedX) # The Z axis is an arbitrary vector cross X arbitrary = [0 for i in range(3)] arbitrary[0] = random.uniform(-10,10) arbitrary[1] = random.uniform(-10,10) arbitrary[2] = random.uniform(-10,10) math.Cross(normalizedX, arbitrary, normalizedZ) math.Normalize(normalizedZ) # The Y axis is Z cross X math.Cross(normalizedZ, normalizedX, normalizedY) matrix = vtk.vtkMatrix4x4() # Create the direction cosine matrix matrix.Identity() for i in range(3): matrix.SetElement(i, 0, normalizedX[i]) matrix.SetElement(i, 1, normalizedY[i]) matrix.SetElement(i, 2, normalizedZ[i]) # Apply the transforms transform = vtk.vtkTransform() transform.Translate(translationTarget) transform.Concatenate(matrix) transform.RotateZ(90) # Create model node probeModel = slicer.vtkMRMLModelNode() probeModel.SetScene(scene) probeModel.SetName(probeText + "-%s" % targetFid.GetName()) probeModel.SetAndObservePolyData(probe.GetOutput()) # Create display node probeModelDisplay = slicer.vtkMRMLModelDisplayNode() probeModelDisplay.SetColor(probeColor) probeModelDisplay.SetOpacity(1) probeModelDisplay.SliceIntersectionVisibilityOn() probeModelDisplay.SetScene(scene) scene.AddNode(probeModelDisplay) probeModel.SetAndObserveDisplayNodeID(probeModelDisplay.GetID()) # Add to scene probeModelDisplay.SetPolyData(probe.GetOutput()) scene.AddNode(probeModel) # Create probeTransform node probeTransform = slicer.vtkMRMLLinearTransformNode() probeTransform.SetName(probeText + 'Transform-%s' % entryPointFid.GetName()) scene.AddNode(probeTransform) probeTransform.ApplyTransformMatrix(transform.GetMatrix()) probeModel.SetAndObserveTransformNodeID(probeTransform.GetID())
def PointsToPlanePolyData( self, inPoints, reverse ): # Create the oriented bounding box # This gives us one plane on the bounding box, not the plane of best fit corner = [ 0, 0, 0 ] maxVector = [ 0, 0, 0 ] midVector = [ 0, 0, 0 ] minVector = [ 0, 0, 0 ] size = [ 0, 0, 0 ] obb = vtk.vtkOBBTree() obb.ComputeOBB( inPoints, corner, maxVector, midVector, minVector, size ) # Calculate the mean of the points on the plane base = self.CalculateMean( inPoints ) relBase = [ 0, 0, 0 ] # Find the projection of the mean point in the minVector direction vtk.vtkMath().Subtract( base, corner, relBase ) normal = minVector[:] vtk.vtkMath().Normalize( normal ) dot = vtk.vtkMath().Dot( relBase, normal ) dot = 0 proj = normal[:] vtk.vtkMath().MultiplyScalar( proj, dot ) print dot # Find the points on the plane origin = [ 0, 0, 0 ] point1 = [ 0, 0, 0 ] point2 = [ 0, 0, 0 ] vtk.vtkMath().Add( corner, proj, origin ) vtk.vtkMath().Add( origin, maxVector, point1 ) vtk.vtkMath().Add( origin, midVector, point2 ) # Construct the plane plane = vtk.vtkPlaneSource() plane.SetOrigin( origin ) plane.SetPoint1( point1 ) plane.SetPoint2( point2 ) plane.Update() return plane.GetOutput()
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