Skip to content

Commit

Permalink
BUG: Recompute EndoscopyLogic fields immediately instead of lazily
Browse files Browse the repository at this point in the history
The logic for when to loadCameraOrientations and recompute EndoscopyLogic
fields was not working in all cases.  The lazy approach to loading and
recomputing could have been modified to fix this, but we did not pursue this
approach because the lazy approach has a flaw: the user interface (e.g. number
of frames available) should be available immediately, not lazily (e.g. only
once the user starts a flythrough).
  • Loading branch information
Leengit authored and jcfr committed Nov 29, 2023
1 parent 3476a2f commit 5e45824
Showing 1 changed file with 22 additions and 34 deletions.
56 changes: 22 additions & 34 deletions Modules/Scripted/Endoscopy/Endoscopy.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ def setupPathUI(self):
inputCurveSelector.addEnabled = False
inputCurveSelector.removeEnabled = False
inputCurveSelector.connect("currentNodeChanged(bool)", self.enableOrDisableCreateButton)
inputCurveSelector.connect("currentNodeChanged(vtkMRMLNode*)", self.setInputCurve)
pathFormLayout.addRow(_("Curve to modify:"), inputCurveSelector)
self.inputCurveSelector = inputCurveSelector

Expand Down Expand Up @@ -312,16 +311,15 @@ def setInputCurve(self, newInputCurve):

if self.inputCurve is not None:
self.removeObserver(self.inputCurve, vtk.vtkCommand.ModifiedEvent, self.onInputCurveModified)

self.inputCurve = newInputCurve

if newInputCurve is not None:
self.addObserver(self.inputCurve, vtk.vtkCommand.ModifiedEvent, self.onInputCurveModified)

if self.logic is not None:
# We are going to have rebuild the EndoscopyLogic later
self.logic.cleanup()
self.logic = None
cameraOrientations = self.loadCameraOrientations()
self.logic = EndoscopyLogic(self.inputCurve, cameraOrientations)

# Update UI
self.updateWidgetFromMRML()
Expand All @@ -347,11 +345,15 @@ def enableOrDisableCreateButton(self):

def onInputCurveModified(self, observer, eventid):
"""If the input curve was changed we need to repopulate the keyframe UI"""
if not self.ignoreInputCurveModified:
if self.logic:
# We are going to have rebuild the EndoscopyLogic later
self.logic.cleanup()
self.logic = None
if self.ignoreInputCurveModified:
return
self.ignoreInputCurveModified += 1
if self.logic:
self.logic.cleanup()
self.logic = None
cameraOrientations = self.loadCameraOrientations()
self.logic = EndoscopyLogic(self.inputCurve, cameraOrientations)
self.ignoreInputCurveModified -= 1

def onCreatePathButtonClicked(self):
"""Connected to 'Use this curve'` button. It allows to:
Expand All @@ -360,12 +362,13 @@ def onCreatePathButtonClicked(self):
- ensure cursor, model and input curve are not visible in the endoscopy view
- go to start of the path
"""
inputCurve = self.inputCurveSelector.currentNode()
if self.ignoreInputCurveModified:
return
self.ignoreInputCurveModified += 1

if self.logic:
self.logic.cleanup()
self.logic = EndoscopyLogic(inputCurve)
inputCurve = self.inputCurveSelector.currentNode()

self.setInputCurve(inputCurve)

numberOfControlPoints = self.logic.resampledCurve.GetNumberOfControlPoints()

Expand Down Expand Up @@ -442,12 +445,7 @@ def onSaveOrientationButtonClicked(self):
cameraOrientations[distanceAlongResampledCurve] = worldOrientation
self.saveCameraOrientations(cameraOrientations)

if not self.logic:
# Create an entire EndoscopyLogic instance
self.logic = EndoscopyLogic(self.inputCurve)
else:
# Update only the interpolations
self.logic.interpolateOrientations()
self.logic.interpolateOrientations()

self.flyTo(resampledCurvePointIndex)

Expand All @@ -469,12 +467,7 @@ def onDeleteOrientationButtonClicked(self):
del cameraOrientations[distanceAlongResampledCurve]
self.saveCameraOrientations(cameraOrientations)

if not self.logic:
# Create an entire EndoscopyLogic instance
self.logic = EndoscopyLogic(self.inputCurve)
else:
# Update only the interpolations
self.logic.interpolateOrientations()
self.logic.interpolateOrientations()

self.flyTo(resampledCurvePointIndex)

Expand Down Expand Up @@ -576,9 +569,6 @@ def cameraOrientationsIsCorrectType(self, convertedCameraOrientations):
)

def flyToNext(self):
if self.logic is None:
# We invalidated self.logic due to an intervening user modification of the input. We need it now.
self.logic = EndoscopyLogic(self.inputCurve)
currentStep = int(self.frameSlider.value)
nextStep = currentStep + self.skip + 1
if nextStep > self.logic.resampledCurve.GetNumberOfControlPoints() - 2:
Expand All @@ -588,10 +578,6 @@ def flyToNext(self):
def flyTo(self, resampledCurvePointIndex):
"""Apply the resampledCurvePointIndex-th step in the path to the global camera"""

if self.logic is None:
# We invalidated self.logic due to an intervening user modification of the input. We need it now.
self.logic = EndoscopyLogic(self.inputCurve)

if (
self.logic.resampledCurve is None
or not 0 <= resampledCurvePointIndex < self.logic.resampledCurve.GetNumberOfControlPoints()
Expand All @@ -615,7 +601,8 @@ def flyTo(self, resampledCurvePointIndex):
)

# Set the cursor matrix
self.transform.SetMatrixTransformToParent(worldMatrix4x4)
if self.transform:
self.transform.SetMatrixTransformToParent(worldMatrix4x4)

# Set the camera & cameraNode
with slicer.util.NodeModify(self.cameraNode):
Expand Down Expand Up @@ -720,8 +707,9 @@ class EndoscopyLogic:

NODE_PATH_CAMERA_ORIENTATIONS_ATTRIBUTE_NAME = "Endoscopy.Path.CameraOrientations"

def __init__(self, inputCurve, dl=0.5):
def __init__(self, inputCurve, cameraOrientations, dl=0.5):
self.cleanup()
self.cameraOrientations = cameraOrientations
self.dl = dl # desired world space step size (in mm)
self.setControlPoints(inputCurve)

Expand Down

0 comments on commit 5e45824

Please sign in to comment.