Updating of the sphere

Hi,

I have been trying to develop a model of a cup. For this I followed the following steps:

  1. Selected two fiducial points.

  2. Based on the fiducial points a sphere is created.

  3. A plane passes through these two fiducial points.

  4. Using the dynamic modeler module, a shell is created. This gives a hollow sphere.

  5. Using the dynamic modeler, the above generated plane cuts the sphere into half. This gives a cup as desired.

  6. 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)

I think you should define the UpdateSphere function after you define the sphere source.

Please let me know if that helps

Mauro

Hi,

It didn’t worked that way. So, I just created two different function and now it works as desired.