From 7bbc2cea19222da2e40646b99230668d78d0bfa9 Mon Sep 17 00:00:00 2001 From: Quinn Williams Date: Thu, 27 Jun 2024 16:50:08 -0400 Subject: [PATCH] ENH: Enable reset simulations --- SlicerSofa/SlicerSofa.py | 12 ++++-- .../Resources/UI/SoftTissueSimulation.ui | 7 ++++ SoftTissueSimulation/SoftTissueSimulation.py | 38 +++++++++++++++++-- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/SlicerSofa/SlicerSofa.py b/SlicerSofa/SlicerSofa.py index 549eab7..2727242 100644 --- a/SlicerSofa/SlicerSofa.py +++ b/SlicerSofa/SlicerSofa.py @@ -70,8 +70,10 @@ def __init__(self) -> None: self._rootNode = None self._simulationRunning = False self._currentStep = 0 - self._totaSteps = 0 + self._totalSteps = 0 self._dt = 0 + self.initialgrid = [] + self.startup = True def setupScene(self, parameterNode): """Setup the simulation scene.""" @@ -91,15 +93,17 @@ def stopSimulation(self) -> None: if self._sceneUp is True: self._simulationRunning = False + def resetSimulation(self, parameterNode=None) -> None: + pass + def simulationStep(self, parameterNode=None) -> None: """Perform a single simulation step.""" - if self._sceneUp is False or self._simulationRunning is False: slicer.util.errorDisplay("Can't advance the simulation forward. Simulation is not running.") return - + parameterNode.modelNode.GetUnstructuredGrid() + self.updateSofa(parameterNode) - if self._currentStep < self._totalSteps: Sofa.Simulation.animate(self._rootNode, self._dt) self._currentStep += 1 diff --git a/SoftTissueSimulation/Resources/UI/SoftTissueSimulation.ui b/SoftTissueSimulation/Resources/UI/SoftTissueSimulation.ui index 346b685..12930f4 100644 --- a/SoftTissueSimulation/Resources/UI/SoftTissueSimulation.ui +++ b/SoftTissueSimulation/Resources/UI/SoftTissueSimulation.ui @@ -353,6 +353,13 @@ + + + + Reset Simulation + + + diff --git a/SoftTissueSimulation/SoftTissueSimulation.py b/SoftTissueSimulation/SoftTissueSimulation.py index e2f91c7..39668b3 100644 --- a/SoftTissueSimulation/SoftTissueSimulation.py +++ b/SoftTissueSimulation/SoftTissueSimulation.py @@ -231,6 +231,7 @@ def setup(self) -> None: self.ui.startSimulationPushButton.connect("clicked()", self.startSimulation) self.ui.stopSimulationPushButton.connect("clicked()", self.stopSimulation) + self.ui.resetSimulationPushButton.connect("clicked()", self.resetSimulation) self.ui.addBoundaryROIPushButton.connect("clicked()", self.logic.addBoundaryROI) self.ui.addGravityVectorPushButton.connect("clicked()", self.logic.addGravityVector) self.ui.addMovingPointPushButton.connect("clicked()", self.logic.addMovingPoint) @@ -298,7 +299,7 @@ def updateSimulationGUI(self, caller, event): def startSimulation(self): self.logic.dt = self.ui.dtSpinBox.value - self.logic.totalSteps = self.ui.totalStepsSpinBox.value + self.logic._totalSteps = self.ui.totalStepsSpinBox.value self.logic.currentStep = self.ui.currentStepSpinBox.value self.logic.startSimulation() self.timer.start(0) #This timer drives the simulation updates @@ -307,8 +308,14 @@ def stopSimulation(self): self.timer.stop() self.logic.stopSimulation() + def resetSimulation(self): + self.timer.stop() + self.ui.currentStepSpinBox.value = 0 + self.logic.resetSimulation() + def simulationStep(self): - self.logic.simulationStep(self.parameterNode) + self.logic.simulationStep(self.parameterNode) + self.ui.currentStepSpinBox.value +=1 # # SoftTissueSimulationLogic @@ -330,6 +337,7 @@ def __init__(self) -> None: self.connectionStatus = 0 self.boxROI = None self.mouseInteractor = None + self.startup = True def updateSofa(self, parameterNode) -> None: if parameterNode is not None: @@ -363,9 +371,11 @@ def getSimulationController(self): return self.simulationController def startSimulation(self) -> None: + sequenceNode = self.getParameterNode().sequenceNode browserNode = self.getParameterNode().sequenceBrowserNode modelNode = self.getParameterNode().modelNode + movingPointNode = self.getParameterNode().movingPointNode # Synchronize and set up the sequence browser node @@ -375,6 +385,12 @@ def startSimulation(self) -> None: browserNode.SetRecording(sequenceNode, True) browserNode.SetRecordingActive(True) + + #if it's the first time running simulation, save the initial mesh points for reset + if self.startup: + self.startup = False + self.initialgrid = self.getParameterNode().getModelPointsArray() + super().startSimulation(self.getParameterNode()) self._simulationRunning = True self.getParameterNode().Modified() @@ -387,6 +403,21 @@ def stopSimulation(self) -> None: browserNode.SetRecordingActive(False) self.getParameterNode().Modified() + def resetSimulation(self) -> None: + self.currentStep = 0 + self.totalSteps = 0 + #reset mesh + points_vtk = numpy_to_vtk(num_array=self.initialgrid, deep=True, array_type=vtk.VTK_FLOAT) + vtk_points = vtk.vtkPoints() + vtk_points.SetData(points_vtk) + self.getParameterNode().modelNode.GetUnstructuredGrid().SetPoints(vtk_points) + #reset simulation + self.stopSimulation() + self.clean() + self.createScene(self.getParameterNode()) + + + def onModelNodeModified(self, caller, event) -> None: if self.getParameterNode().modelNode.GetUnstructuredGrid() is not None: self.getParameterNode().modelNode.GetUnstructuredGrid().SetPoints(caller.GetPolyData().GetPoints()) @@ -410,7 +441,6 @@ def addBoundaryROI(self) -> None: size = [abs(bounds[1] - bounds[0])/2.0, abs(bounds[3] - bounds[2])/2.0, abs(bounds[5] - bounds[4])/2.0] roiNode.SetXYZ(center) roiNode.SetRadiusXYZ(size[0], size[1], size[2]) - self.getParameterNode().boundaryROI = roiNode def addGravityVector(self) -> None: @@ -531,7 +561,6 @@ def createScene(self, parameterNode) -> Sofa.Core.Node: from stlib3.physics.deformable import ElasticMaterialObject from stlib3.physics.rigid import Floor from splib3.numerics import Vec3 - rootNode = Sofa.Core.Node() MainHeader(rootNode, plugins=[ @@ -586,6 +615,7 @@ def createScene(self, parameterNode) -> Sofa.Core.Node: femNode.addObject('TetrahedronFEMForceField', name="FEM", youngModulus=1.5, poissonRatio=0.45, method="large") femNode.addObject('MeshMatrixMass', totalMass=1) + fixedROI = femNode.addChild('FixedROI') self.BoxROI = fixedROI.addObject('BoxROI', template="Vec3", box=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0], drawBoxes=False, position="@../mstate.rest_position", name="FixedROI",