Hi,
I have been trying to develop a model of a cup. For this I followed the following steps:
-
Selected two fiducial points.
-
Based on the fiducial points a sphere is created.
-
A plane passes through these two fiducial points.
-
Using the dynamic modeler module, a shell is created. This gives a hollow sphere.
-
Using the dynamic modeler, the above generated plane cuts the sphere into half. This gives a cup as desired.
-
Now I have also added the capability to rotate the cup as desired. The remaining sphere and the plane rotates together. This is the desired effect.
The issue I am facing is that now I am unable to update the radius of the sphere dynamically. I have also added an observor to detect any change in the position of the sphere and update it accordingly.
I have attached the code.
Thanks
def CreateSphere(self):
def UpdateSphere(param1, param2):
“”“Update the sphere from the control points
“””
import math
pointListNode = slicer.util.getNode(“F”)
centerPointCoord = [0.0, 0.0, 0.0]
pointListNode.GetNthControlPointPosition(0,centerPointCoord)
circumferencePointCoord = [0.0, 0.0, 0.0]
pointListNode.GetNthControlPointPosition(1,circumferencePointCoord)
sphere.SetCenter(centerPointCoord)
radius=math.sqrt((centerPointCoord[0]-circumferencePointCoord[0])**2+(centerPointCoord[1]-circumferencePointCoord[1])**2+(centerPointCoord[2]-circumferencePointCoord[2])**2)
sphere.SetRadius(radius)
sphere.SetPhiResolution(30)
sphere.SetThetaResolution(30)
sphere.Update()
# Get point list node from scene
pointListNode = slicer.util.getNode("F")
#print(pointListNode)
sphere = vtk.vtkSphereSource()
UpdateSphere(0,0)
# Create model node and add to scene
modelsLogic = slicer.modules.models.logic()
model = modelsLogic.AddModel(sphere.GetOutput())
model.GetDisplayNode().SetSliceIntersectionVisibility(True)
model.GetDisplayNode().SetSliceIntersectionThickness(3)
model.GetDisplayNode().SetColor(1,1,0)
# Call UpdateSphere whenever the control points are changed
pointListNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent, UpdateSphere, 2)
# Compute best fit plane
# translatedLineStartPoint = np.zeros(3)
#center = pointListNode.GetNthControlPointPosition(0,translatedLineStartPoint)
# translatedLineStopPoint = np.zeros(3)
# circumference = pointListNode.GetNthControlPointPosition(0,translatedLineStopPoint)
#normal = np.cross(center, circumference)
#print(normal)
#print(pointListNode.GetNthControlPointPosition(0,translatedLineStartPoint))
center = [10.0, 0.0, 0.0]
normal = [0.0, 0.0, 1.0]
vtk.vtkPlane.ComputeBestFittingPlane(model.GetPolyData().GetPoints(), center, normal)
# Display best fit plane as a markups plane
planeNode = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLMarkupsPlaneNode')
planeNode.SetCenter(center)
planeNode.SetNormal(normal)
planeNode.SetName("MarkupsPlane")
hollowModeler = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLDynamicModelerNode")
hollowModeler.SetToolName("Hollow")
hollowModeler.SetNodeReferenceID("Hollow.InputModel", model.GetID())
#hollowedModelNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode") # this node will store the hollow model
hollowModeler.SetNodeReferenceID("Hollow.OutputModel", model.GetID())
hollowModeler.SetAttribute("ShellThickness", "2.5") # grow outside
hollowModeler.SetContinuousUpdate(True) # auto-update output model if input parameters are changed
#hollowModeler.SetNodeReferenceID("PlaneCut.OutputPositiveModel", PlaneCuttedModelNode.GetID())
slicer.modules.dynamicmodeler.logic().RunDynamicModelerTool(hollowModeler)
# Set up Plane Cut tool
PlaneModeler = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLDynamicModelerNode")
PlaneModeler.SetToolName("Plane cut")
PlaneModeler.SetNodeReferenceID("PlaneCut.InputModel", model.GetID())
PlaneModeler.SetNodeReferenceID("PlaneCut.InputPlane", planeNode.GetID())
PlaneCuttedModelNode = slicer.mrmlScene.AddNewNodeByClass("vtkMRMLModelNode") # this node will store the hollow model
PlaneModeler.SetNodeReferenceID("PlaneCut.OutputModel", model.GetID())
PlaneModeler.SetAttribute("OperationType", "Union") # grow outside
PlaneModeler.SetContinuousUpdate(True) # auto-update output model if input parameters are changed
PlaneModeler.SetNodeReferenceID("PlaneCut.OutputPositiveModel", model.GetID())
slicer.modules.dynamicmodeler.logic().RunDynamicModelerTool(PlaneModeler)
PlaneNode = slicer.util.getNode('MarkupsPlane')
PlaneNode.SetPlaneType(PlaneNode.PlaneType3Points)
displayNode = PlaneNode.GetDisplayNode()
displayNode.SetGlyphScale(2.5)
displayNode.HandlesInteractiveOn()
displayNode.SetRotationHandleVisibility(True)
displayNode.SetTranslationHandleVisibility(True)
planeToWorldTransformNode = slicer.vtkMRMLLinearTransformNode()
planeToWorldTransformNode.SetName(slicer.mrmlScene.GetUniqueNameByString("planeToWorld"))
slicer.mrmlScene.AddNode(planeToWorldTransformNode)
# Save the inverse of the initial transform of the plane
worldToInitialModelTransformNode = slicer.vtkMRMLLinearTransformNode()
worldToInitialModelTransformNode.SetName(slicer.mrmlScene.GetUniqueNameByString("worldToInitialModel"))
slicer.mrmlScene.AddNode(worldToInitialModelTransformNode)
model.SetAndObserveTransformNodeID(worldToInitialModelTransformNode.GetID())
worldToInitialModelTransformNode.SetAndObserveTransformNodeID(planeToWorldTransformNode.GetID())
# function to update the model's position/orientation interactively
def onPlaneModified(sourceNode,event=None):
planeToWorldMatrix = vtk.vtkMatrix4x4()
try:
sourceNode.GetObjectToWorldMatrix(planeToWorldMatrix)
except:
sourceNode.GetPlaneToWorldMatrix(planeToWorldMatrix)
#
planeNodeToWorldTransformNode = model.GetParentTransformNode().GetParentTransformNode()
planeNodeToWorldTransformNode.SetMatrixTransformToParent(planeToWorldMatrix)
onPlaneModified(planeNode)
planeToWorldMatrix = vtk.vtkMatrix4x4()
# This call is done to give the transformNode time to update its matrixToParent
planeNodeToWorldTransformNode = model.GetParentTransformNode().GetParentTransformNode()
planeNodeToWorldTransformNode.GetMatrixTransformToParent(planeToWorldMatrix)
worldToInitialModelMatrix = vtk.vtkMatrix4x4()
worldToInitialModelMatrix.DeepCopy(planeToWorldMatrix)
worldToInitialModelMatrix.Invert()
worldToInitialModelTransformNode.SetMatrixTransformToParent(worldToInitialModelMatrix)
observer = planeNode.AddObserver(slicer.vtkMRMLMarkupsNode.PointModifiedEvent,onPlaneModified)