def registerObject(self, object_type, name, cpp, vtk_object, vtk_light): if type(vtk_object) is dict: mapper = {} actor = {} bbox = vtk.vtkBoundingBox() for key, components in vtk_object.items(): mapper[key] = {} actor[key] = {} for id, polydata in components.items(): object_mapper, object_actor = self.addVTKObject(polydata) if polydata.GetNumberOfPoints() != 0: bbox.AddBox(self.bbox(object_actor)) mapper[key][id] = object_mapper actor[key][id] = object_actor else: mapper, actor = self.addVTKObject(vtk_object) bbox = self.bbox(actor) id = str(uuid()) print(id) self.getDataBase()[id] = { "type": object_type, "name": name, "cpp": cpp, "bbox": bbox, "vtk": vtk_object, "actor": actor, "mapper": mapper } return {"id": id, "name": name, "type": object_type, "data": vtk_light}
def outputVolumeGeometry(self): # spacing spacingScale = numpy.array([1.0, 1.0, 1 + self.sliceSkip]) if self.outputQuality == 'half': spacingScale *= 2.0 elif self.outputQuality == 'preview': spacingScale *= 4.0 ijkToRAS = numpy.dot( self.originalVolumeIJKToRAS, numpy.diag( [spacingScale[0], spacingScale[1], spacingScale[2], 1.0])) # extent fullExtent = [0, 0, 0, 0, 0, 0] for i in range(3): fullExtent[i * 2 + 1] = int( math.floor( self.originalVolumeDimensions[i] / spacingScale[i])) - 1 if self.outputVolumeBounds: rasToIJK = numpy.linalg.inv(ijkToRAS) extentIJK = vtk.vtkBoundingBox() for cornerR in [ self.outputVolumeBounds[0], self.outputVolumeBounds[1] ]: for cornerA in [ self.outputVolumeBounds[2], self.outputVolumeBounds[3] ]: for cornerS in [ self.outputVolumeBounds[4], self.outputVolumeBounds[5] ]: cornerIJK = numpy.dot( rasToIJK, [cornerR, cornerA, cornerS, 1.0])[0:3] extentIJK.AddPoint(cornerIJK) extent = [0, 0, 0, 0, 0, 0] for i in range(3): extent[i * 2] = int( math.floor(extentIJK.GetBound(i * 2) - 0.5)) if extent[i * 2] < fullExtent[i * 2]: extent[i * 2] = fullExtent[i * 2] extent[i * 2 + 1] = int( math.ceil(extentIJK.GetBound(i * 2 + 1) + 0.5)) if extent[i * 2 + 1] > fullExtent[i * 2 + 1]: extent[i * 2 + 1] = fullExtent[i * 2 + 1] else: extent = fullExtent # origin originRAS = numpy.dot(ijkToRAS, [extent[0], extent[2], extent[4], 1.0])[0:3] ijkToRAS[0:3, 3] = originRAS numberOfScalarComponents = 1 if self.outputGrayscale else self.originalVolumeNumberOfScalarComponents return ijkToRAS, extent, numberOfScalarComponents
def menu(self, x, y, ids): renderer = self.getRenderer() picker = vtk.vtkWorldPointPicker() ret = picker.Pick([x, y, 0], renderer) point = picker.GetPickPosition() epsilon = self.computeEpsilon(renderer, point[2]) bbox = vtk.vtkBoundingBox() bbox.AddPoint(point[0] + epsilon, point[1] + epsilon, point[2] + epsilon) bbox.AddPoint(point[0] - epsilon, point[1] - epsilon, point[2] - epsilon) for id in ids: if self.getObject(id)['bbox'].Intersects(bbox): return id return 0
def onCreateROI(self, roiNode): if self.inputPath is None: slicer.mrmlScene.RemoveNode(roiNode) return bounds = numpy.zeros(6) self.inputPath.GetRASBounds(bounds) box = vtk.vtkBoundingBox(bounds) center = [0.0, 0.0, 0.0] box.GetCenter(center) roiNode.SetName("ROI " + self.inputPath.GetName()) roiNode.SetXYZ(center) roiNode.SetRadiusXYZ( box.GetLength(0) / 2, box.GetLength(1) / 2, box.GetLength(2) / 2)
def preFitROI(self): inputFiducialNode = self.ui.inputFiducialSelector.currentNode() inputROINode = self.ui.inputROISelector.currentNode() if (inputFiducialNode is None) or (inputROINode is None): return fiducialBounds = np.zeros(6) inputFiducialNode.GetBounds(fiducialBounds) vFiducialBounds=vtk.vtkBoundingBox() vFiducialBounds.SetBounds(fiducialBounds) center = np.zeros(3) vFiducialBounds.GetCenter(center) inputROINode.SetCenter(center) lengths = np.zeros(3) vFiducialBounds.GetLengths(lengths) inputROINode.SetRadiusXYZ((lengths[0] / 2, lengths[1] / 2, lengths[2] / 2)) inputROINode.SetDisplayVisibility(True)
timer.StopTimer() time = timer.GetElapsedTime() print("vtkPoints::ComputeBounds():") print("\tTime: {0}".format(time)) print("\tBounds: {0}".format(box)) assert box[0] == -1.5 assert box[1] == 1.5 assert box[2] == -0.5 assert box[3] == 0.5 assert box[4] == 0.0 assert box[5] == 0.0 # Uses vtkBoundingBox with vtkSMPTools. This method takes into account # an (optional) pointUses array to only consider selected points. bbox = vtk.vtkBoundingBox() timer.StartTimer() bbox.ComputeBounds(points, box) timer.StopTimer() time = timer.GetElapsedTime() print("vtkBoundingBox::ComputeBounds():") print("\tTime: {0}".format(time)) print("\tBounds: {0}".format(box)) assert box[0] == -1.5 assert box[1] == 1.5 assert box[2] == -0.5 assert box[3] == 0.5 assert box[4] == 0.0 assert box[5] == 0.0
locator.AutomaticOff() locator.SetDivisions(0,2,10) locator.Modified() locator.BuildLocator() print("Divisions: {0}".format( locator.GetDivisions() )) ndivs = locator.GetDivisions() if ndivs[0] != 1 or ndivs[1] != 2 or ndivs[2] != 10: error = 1 # Test the vtkBoundingBox code targetBins = 2500 print("\nTesting vtkBoundingBox w/ {} target bins".format(targetBins)) divs = [1,1,1] bounds = [0,0,0,0,0,0] bds = [0,0,0,0,0,0] bbox = vtk.vtkBoundingBox() # Degenerate bbox.SetBounds(0,0,1,1,2,2) bbox.ComputeDivisions(targetBins,bounds,divs) bbox.GetBounds(bds) print("BBox bounds: ({},{}, {},{}, {},{})".format(bds[0],bds[1],bds[2],bds[3],bds[4],bds[5])) print(" Adjusted bounds: ({},{}, {},{}, {},{})".format(bounds[0],bounds[1],bounds[2],bounds[3],bounds[4],bounds[5])) print(" Divisions: ({},{},{})".format(divs[0],divs[1],divs[2])) if divs[0] != 1 or divs[1] != 1 or divs[2] != 1: error = 1 # Line bbox.SetBounds(0,0,1,1,5,10) bbox.ComputeDivisions(targetBins,bounds,divs) bbox.GetBounds(bds)
def bbox(self, actor): bounds = actor.GetBounds() bbox = vtk.vtkBoundingBox(bounds) return bbox
def run(self, meshNode, LMNode, gridLandmarks, sampleRate): surfacePolydata = meshNode.GetPolyData() gridPoints = vtk.vtkPoints() gridPoints.InsertNextPoint(0, 0, 0) gridPoints.InsertNextPoint(0, sampleRate - 1, 0) gridPoints.InsertNextPoint(sampleRate - 1, 0, 0) for row in range(1, sampleRate - 1): for col in range(1, sampleRate - 1): if (row + col) < (sampleRate - 1): gridPoints.InsertNextPoint(row, col, 0) gridPolydata = vtk.vtkPolyData() gridPolydata.SetPoints(gridPoints) sourcePoints = vtk.vtkPoints() targetPoints = vtk.vtkPoints() #sourcePoints.InsertNextPoint(gridPoints.GetPoint(0)) #sourcePoints.InsertNextPoint(gridPoints.GetPoint(sampleRate-1)) #sourcePoints.InsertNextPoint(gridPoints.GetPoint(gridPoints.GetNumberOfPoints()-1)) sourcePoints.InsertNextPoint(gridPoints.GetPoint(0)) sourcePoints.InsertNextPoint(gridPoints.GetPoint(1)) sourcePoints.InsertNextPoint(gridPoints.GetPoint(2)) point = [0, 0, 0] for gridVertex in gridLandmarks: LMNode.GetMarkupPoint(int(gridVertex - 1), 0, point) targetPoints.InsertNextPoint(point) #transform grid to triangle transform = vtk.vtkThinPlateSplineTransform() transform.SetSourceLandmarks(sourcePoints) transform.SetTargetLandmarks(targetPoints) transform.SetBasisToR() transformNode = slicer.mrmlScene.AddNewNodeByClass( "vtkMRMLTransformNode", "TPS") transformNode.SetAndObserveTransformToParent(transform) model = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode", "mesh_resampled") model.SetAndObservePolyData(gridPolydata) model.SetAndObserveTransformNodeID(transformNode.GetID()) slicer.vtkSlicerTransformLogic().hardenTransform(model) resampledPolydata = model.GetPolyData() pointLocator = vtk.vtkPointLocator() pointLocator.SetDataSet(surfacePolydata) pointLocator.BuildLocator() #get surface normal from each landmark point rayDirection = [0, 0, 0] normalArray = surfacePolydata.GetPointData().GetArray("Normals") if (not normalArray): normalFilter = vtk.vtkPolyDataNormals() normalFilter.ComputePointNormalsOn() normalFilter.SetInputData(surfacePolydata) normalFilter.Update() normalArray = normalFilter.GetOutput().GetPointData().GetArray( "Normals") if (not normalArray): print("Error: no normal array") for gridVertex in gridLandmarks: LMNode.GetMarkupPoint(int(gridVertex - 1), 0, point) closestPointId = pointLocator.FindClosestPoint(point) tempNormal = normalArray.GetTuple(closestPointId) rayDirection[0] += tempNormal[0] rayDirection[1] += tempNormal[1] rayDirection[2] += tempNormal[2] #calculate average for dim in range(len(rayDirection)): rayDirection[dim] = rayDirection[dim] / 4 #set up locater for intersection with normal vector rays obbTree = vtk.vtkOBBTree() obbTree.SetDataSet(surfacePolydata) obbTree.BuildLocator() #define new landmark sets semilandmarkNodeName = "semiLM_" + str(gridLandmarks[0]) + "_" + str( gridLandmarks[1]) + "_" + str(gridLandmarks[2]) semilandmarkPoints = slicer.mrmlScene.AddNewNodeByClass( "vtkMRMLMarkupsFiducialNode", semilandmarkNodeName) #get a sample distance for quality control m1 = model.GetPolyData().GetPoint(0) m2 = model.GetPolyData().GetPoint(1) m3 = model.GetPolyData().GetPoint(1) d1 = math.sqrt(vtk.vtkMath().Distance2BetweenPoints(m1, m2)) d2 = math.sqrt(vtk.vtkMath().Distance2BetweenPoints(m2, m3)) d3 = math.sqrt(vtk.vtkMath().Distance2BetweenPoints(m1, m3)) sampleDistance = (d1 + d2 + d3) # set initial three grid points for index in range(0, 3): origLMPoint = resampledPolydata.GetPoint(index) #landmarkLabel = LMNode.GetNthFiducialLabel(gridLandmarks[index]-1) landmarkLabel = str(gridLandmarks[index]) semilandmarkPoints.AddFiducialFromArray(origLMPoint, landmarkLabel) # calculate maximum projection distance projectionTolerance = 2 boundingBox = vtk.vtkBoundingBox() boundingBox.AddBounds(surfacePolydata.GetBounds()) diagonalDistance = boundingBox.GetDiagonalLength() #rayLength = math.sqrt(diagonalDistance) * projectionTolerance rayLength = sampleDistance # get normal projection intersections for remaining semi-landmarks print("Target number of points: ", resampledPolydata.GetNumberOfPoints()) for index in range(3, resampledPolydata.GetNumberOfPoints()): modelPoint = resampledPolydata.GetPoint(index) rayEndPoint = [0, 0, 0] for dim in range(len(rayEndPoint)): rayEndPoint[ dim] = modelPoint[dim] + rayDirection[dim] * rayLength intersectionIds = vtk.vtkIdList() intersectionPoints = vtk.vtkPoints() obbTree.IntersectWithLine(modelPoint, rayEndPoint, intersectionPoints, intersectionIds) #if there are intersections, update the point to most external one. if intersectionPoints.GetNumberOfPoints() > 0: exteriorPoint = intersectionPoints.GetPoint( intersectionPoints.GetNumberOfPoints() - 1) #projectionDistance=math.sqrt(vtk.vtkMath().Distance2BetweenPoints(exteriorPoint, modelPoint)) semilandmarkPoints.AddFiducialFromArray(exteriorPoint) #if there are no intersections, reverse the normal vector else: for dim in range(len(rayEndPoint)): rayEndPoint[ dim] = modelPoint[dim] + rayDirection[dim] * -rayLength obbTree.IntersectWithLine(modelPoint, rayEndPoint, intersectionPoints, intersectionIds) if intersectionPoints.GetNumberOfPoints() > 0: exteriorPoint = intersectionPoints.GetPoint(0) semilandmarkPoints.AddFiducialFromArray(exteriorPoint) #projectionDistance=math.sqrt(vtk.vtkMath().Distance2BetweenPoints(exteriorPoint, modelPoint)) #if projectionDistance < sampleDistance: # semilandmarkPoints.AddFiducialFromArray(exteriorPoint) #else: # closestPointId = pointLocator.FindClosestPoint(modelPoint) # rayOrigin = surfacePolydata.GetPoint(closestPointId) # semilandmarkPoints.AddFiducialFromArray(rayOrigin) #if none in reverse direction, use closest mesh point else: closestPointId = pointLocator.FindClosestPoint(modelPoint) rayOrigin = surfacePolydata.GetPoint(closestPointId) semilandmarkPoints.AddFiducialFromArray(rayOrigin) # update lock status and color semilandmarkPoints.SetLocked(True) semilandmarkPoints.GetDisplayNode().SetColor(random.random(), random.random(), random.random()) semilandmarkPoints.GetDisplayNode().SetSelectedColor( random.random(), random.random(), random.random()) semilandmarkPoints.GetDisplayNode().PointLabelsVisibilityOff() #clean up slicer.mrmlScene.RemoveNode(transformNode) slicer.mrmlScene.RemoveNode(model) print("Total points:", semilandmarkPoints.GetNumberOfFiducials()) return semilandmarkPoints
def GetDiagonalFromBounds(bounds): box = vtk.vtkBoundingBox(bounds) box.SetBounds(bounds) distance = box.GetDiagonalLength() return distance