diff --git a/BoneReconstructionPlanner/BoneReconstructionPlanner.py b/BoneReconstructionPlanner/BoneReconstructionPlanner.py
index 1d30611..457dc97 100644
--- a/BoneReconstructionPlanner/BoneReconstructionPlanner.py
+++ b/BoneReconstructionPlanner/BoneReconstructionPlanner.py
@@ -250,12 +250,15 @@ def setup(self):
)
updateVSPButtonsLayout = self.ui.updateVSPButtonsFrame.layout()
- updateVSPButtonsLayout.setWidget(0, 0, generateFibulaPlanesFibulaBonePiecesAndTransformThemToMandibleButton)
+ updateVSPButtonsLayout.insertWidget(0, generateFibulaPlanesFibulaBonePiecesAndTransformThemToMandibleButton)
self.ui.generateFibulaPlanesFibulaBonePiecesAndTransformThemToMandibleButton = generateFibulaPlanesFibulaBonePiecesAndTransformThemToMandibleButton
recycleIconPath = os.path.join(os.path.dirname(__file__), 'Resources/Icons/recycle_48.svg')
self.ui.hardVSPUpdateButton.setIcon(qt.QIcon(recycleIconPath))
+
+ lockIconPath = os.path.join(os.path.dirname(__file__), 'Resources/Icons/lock_48.svg')
+ self.ui.lockVSPButton.setIcon(qt.QIcon(lockIconPath))
booleanOperationsIconPath = os.path.join(os.path.dirname(__file__), 'Resources/Icons/construction_48.svg')
self.ui.create3DModelOfTheReconstructionButton.setIcon(qt.QIcon(booleanOperationsIconPath))
@@ -350,6 +353,7 @@ def setup(self):
self.ui.createPlateCurveButton.connect('clicked(bool)', self.onCreatePlateCurveButton)
self.ui.createCustomPlateButton.connect('clicked(bool)', self.onCreateCustomPlateButton)
self.ui.hardVSPUpdateButton.connect('clicked(bool)', self.onHardVSPUpdateButton)
+ self.ui.lockVSPButton.connect('toggled(bool)', self.onLockVSPButton)
self.ui.makeAllMandiblePlanesRotateTogetherCheckBox.connect('stateChanged(int)', self.updateParameterNodeFromGUI)
self.ui.useMoreExactVersionOfPositioningAlgorithmCheckBox.connect('stateChanged(int)', self.updateParameterNodeFromGUI)
self.ui.useNonDecimatedBoneModelsForPreviewCheckBox.connect('stateChanged(int)', self.updateParameterNodeFromGUI)
@@ -671,6 +675,37 @@ def updateGUIFromParameterNode(self, caller=None, event=None):
self.ui.customTitaniumPlateGenerationCollapsibleButton.hide()
+ shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
+ mandibularPlanesFolder = shNode.GetItemByName("Mandibular planes")
+ mandibularPlanesList = createListFromFolderID(mandibularPlanesFolder)
+ if self._parameterNode.GetParameter("lockVSP") == "True":
+ self.logic.setInteractiveHandlesVisibilityOfMarkups(
+ mandibularPlanesList,
+ visibility=False
+ )
+ self.logic.setMarkupsListLocked(mandibularPlanesList,locked=True)
+ self.logic.removeMandiblePlaneObservers()
+ #
+ self.ui.lockVSPButton.checked = True
+ self.ui.parametersOfVSPFrame.enabled = False
+ self.ui.updateVSPButtonsFrame.enabled = False
+ self.ui.create3DModelOfTheReconstructionButton.enabled = False
+
+ else:
+ self.logic.setInteractiveHandlesVisibilityOfMarkups(
+ mandibularPlanesList,
+ visibility=True
+ )
+ self.logic.setMarkupsListLocked(mandibularPlanesList,locked=False)
+ self.logic.removeMandiblePlaneObservers() # in case they already exist
+ self.logic.addMandiblePlaneObservers()
+ #
+ self.ui.lockVSPButton.checked = False
+ self.ui.parametersOfVSPFrame.enabled = True
+ self.ui.updateVSPButtonsFrame.enabled = True
+ self.ui.create3DModelOfTheReconstructionButton.enabled = True
+
+
if self._parameterNode.GetParameter("updateOnMandiblePlanesMovement") == "True":
self.ui.generateFibulaPlanesFibulaBonePiecesAndTransformThemToMandibleButton.checkState = 2
else:
@@ -924,6 +959,9 @@ def onCenterFibulaLineButton(self):
def onHardVSPUpdateButton(self):
self.logic.hardVSPUpdate()
+
+ def onLockVSPButton(self,checked):
+ self.logic.lockVSP(checked)
def setBiggerSawBoxesInteractionHandlesVisibility(self, visibility):
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
@@ -1037,6 +1075,8 @@ def setDefaultParameters(self, parameterNode):
parameterNode.SetParameter("showBiggerSawBoxesInteractionHandles","False")
if not parameterNode.GetParameter("showMandiblePlanesInteractionHandles"):
parameterNode.SetParameter("showMandiblePlanesInteractionHandles","True")
+ if not parameterNode.GetParameter("lockVSP"):
+ parameterNode.SetParameter("lockVSP","False")
def getParentFolderItemID(self):
shNode = slicer.vtkMRMLSubjectHierarchyNode.GetSubjectHierarchyNode(slicer.mrmlScene)
@@ -1228,6 +1268,12 @@ def onPlaneModifiedTimer(self,sourceNode,event):
self.generateFibulaPlanesTimer.start()
def onGenerateFibulaPlanesTimerTimeout(self):
+ parameterNode = self.getParameterNode()
+ lockVSPChecked = parameterNode.GetParameter("lockVSP") == "True"
+ if lockVSPChecked:
+ logging.info('VSP updates are locked. Please set "lockVSP" parameter to "False".')
+ return
+
import time
startTime = time.time()
logging.info('Processing started')
@@ -2136,6 +2182,10 @@ def hardVSPUpdate(self):
self.resetPlan()
self.onGenerateFibulaPlanesTimerTimeout()
+ def lockVSP(self, doLock):
+ parameterNode = self.getParameterNode()
+ parameterNode.SetParameter("lockVSP", str(doLock))
+
def generateFibulaPlanesFibulaBonePiecesAndTransformThemToMandible(self):
parameterNode = self.getParameterNode()
useNonDecimatedBoneModelsForPreviewChecked = parameterNode.GetParameter("useNonDecimatedBoneModelsForPreview") == "True"
diff --git a/BoneReconstructionPlanner/Resources/Icons/lock_48.svg b/BoneReconstructionPlanner/Resources/Icons/lock_48.svg
new file mode 100644
index 0000000..4c1938b
--- /dev/null
+++ b/BoneReconstructionPlanner/Resources/Icons/lock_48.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/BoneReconstructionPlanner/Resources/UI/BoneReconstructionPlanner.ui b/BoneReconstructionPlanner/Resources/UI/BoneReconstructionPlanner.ui
index b500c77..768ae8d 100644
--- a/BoneReconstructionPlanner/Resources/UI/BoneReconstructionPlanner.ui
+++ b/BoneReconstructionPlanner/Resources/UI/BoneReconstructionPlanner.ui
@@ -6,8 +6,8 @@
0
0
- 642
- 3288
+ 686
+ 3625
@@ -18,445 +18,552 @@
-
-
-
- Qt::AlignCenter
-
-
- 0
-
-
-
-
-
- Current Scalar Volume
-
-
-
- -
-
-
- true
-
-
-
- vtkMRMLScalarVolumeNode
-
-
-
- false
-
-
- false
-
-
-
- -
-
-
- Right side leg
-
-
-
- -
-
-
- (tick if fibula is the one from the right leg)
-
-
- false
-
-
-
- -
-
-
- Select mandibular segmentation
-
-
-
- -
-
-
- true
-
-
-
- vtkMRMLSegmentationNode
-
-
-
- false
-
-
- false
-
-
-
- -
-
-
- Select fibula segmentation
-
-
-
- -
-
-
- true
-
-
-
- vtkMRMLSegmentationNode
-
-
-
- false
-
-
- false
-
-
-
- -
-
-
- Place mandibular curve
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Add mandibular curve
-
-
-
- -
-
-
- Place fibula line
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- Add fibula line
-
-
-
- -
-
-
- Place mandibular planes
-
-
-
- -
-
-
- Add cut plane
-
-
-
- -
-
-
- Initial space (mm)
-
-
-
- -
-
-
- 1
-
-
-
- -
-
-
- Intersection distance multiplier
-
-
-
- -
-
-
- 1
-
-
- 30.000000000000000
-
-
- 0.100000000000000
-
-
- 1.000000000000000
-
-
-
- -
-
-
- Between space (mm)
-
-
-
- -
-
-
- 1
-
-
- 1.000000000000000
-
-
-
- -
-
-
- Security margin (mm)
-
-
-
- -
-
-
- 1
-
-
- 30.000000000000000
-
-
- 0.100000000000000
-
-
- 1.000000000000000
-
-
-
- -
-
-
- Select mandible curve
-
-
-
- -
-
-
- true
-
-
-
- vtkMRMLMarkupsCurveNode
-
-
-
- false
-
-
- false
-
-
-
- -
-
-
- Select fibula line
-
-
-
- -
-
-
- true
-
-
-
- vtkMRMLMarkupsLineNode
-
-
-
- false
-
-
- false
-
-
-
-
-
- -
-
-
- Create bone models from segmentations
-
-
-
- -
-
-
- Center fibula line using fibula model
-
-
-
- -
-
-
- Show mandible planes interaction handles
-
-
-
- -
-
-
- Show original mandible model
+
+
+
+ 0
+ 0
+
-
-
- -
-
-
- 0
+
+ QFrame::NoFrame
-
- 0
+
+ QFrame::Plain
-
-
-
-
- Show fibula segments lengths
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Fibula segment measurement mode. Needs update
-
-
- QComboBox::AdjustToMinimumContentsLength
-
-
-
-
- center2center
+
+
-
+
+
+ 0
+
+
+ 0
-
- -
+
-
+
+
+ Current Scalar Volume
+
+
+
+ -
+
+
+ true
+
+
+
+ vtkMRMLScalarVolumeNode
+
+
+
+ false
+
+
+ false
+
+
+
+ -
+
+
+ Right side leg
+
+
+
+ -
+
+
+ (tick if fibula is the one from the right leg)
+
+
+ false
+
+
+
+ -
+
+
+ Select mandibular segmentation
+
+
+
+ -
+
+
+ true
+
+
+
+ vtkMRMLSegmentationNode
+
+
+
+ false
+
+
+ false
+
+
+
+ -
+
+
+ Select fibula segmentation
+
+
+
+ -
+
+
+ true
+
+
+
+ vtkMRMLSegmentationNode
+
+
+
+ false
+
+
+ false
+
+
+
+ -
+
+
+ Place mandibular curve
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Add mandibular curve
+
+
+
+ -
+
+
+ Place fibula line
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Add fibula line
+
+
+
+ -
+
+
+ Place mandibular planes
+
+
+
+ -
+
+
+ Add cut plane
+
+
+
+ -
+
+
+ Initial space (mm)
+
+
+
+ -
+
+
+ 1
+
+
+
+ -
+
+
+ Intersection distance multiplier
+
+
+
+ -
+
+
+ 1
+
+
+ 30.000000000000000
+
+
+ 0.100000000000000
+
+
+ 1.000000000000000
+
+
+
+ -
+
+
+ Between space (mm)
+
+
+
+ -
+
+
+ 1
+
+
+ 1.000000000000000
+
+
+
+ -
+
+
+ Security margin (mm)
+
+
+
+ -
+
+
+ 1
+
+
+ 30.000000000000000
+
+
+ 0.100000000000000
+
+
+ 1.000000000000000
+
+
+
+ -
+
+
+ Select mandible curve
+
+
+
+ -
+
+
+ true
+
+
+
+ vtkMRMLMarkupsCurveNode
+
+
+
+ false
+
+
+ false
+
+
+
+ -
+
+
+ Select fibula line
+
+
+
+ -
+
+
+ true
+
+
+
+ vtkMRMLMarkupsLineNode
+
+
+
+ false
+
+
+ false
+
+
+
+
+
+ -
+
- proximal2proximal
+ Create bone models from segmentations
-
- -
+
+
+ -
+
- distal2distal
+ Center fibula line using fibula model
-
-
-
-
-
- -
-
-
- 0
-
-
- 0
-
-
-
-
-
-
+
+
+ -
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Fibula segment lengths measurements
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Fibula segment measurement mode. Needs update
+
+
+ QComboBox::AdjustToMinimumContentsLength
+
+
-
+
+ center2center
+
+
+ -
+
+ proximal2proximal
+
+
+ -
+
+ distal2distal
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
+ 0
+
+
-
+
+
-
+
+ Segmental Mandibulectomy
+
+
+ -
+
+ Hemimandibulectomy
+
+
+
+
+ -
+
+
-
+
+ Removing right side
+
+
+ -
+
+ Removing left side
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
- Segmental Mandibulectomy
+ Automatic mandibular planes positioning for maximum bones contact area
-
- -
+
+
+ -
+
- Hemimandibulectomy
+ Make all mandible planes rotate together
+
+
+
+ -
+
+
+ Use when you have finished editing
-
-
-
- -
-
-
-
- Removing right side
+ Use more exact version of the positioning algorithm (takes more time)
-
- -
+
+
+ -
+
- Removing left side
+ Use non-decimated bone models for preview (takes more time)
-
- -
+
+
+ -
+
-
+ Fix cut goes through the mandible twice
-
-
-
-
-
- -
-
-
- Automatic mandibular planes positioning for maximum bones contact area
-
-
-
- -
-
-
- Make all mandible planes rotate together
-
+
+
+
-
-
-
- Use when you have finished editing
-
-
- Use more exact version of the positioning algorithm (takes more time)
+
+
+
+ 100
+ 100
+
-
-
- -
-
-
- Use non-decimated bone models for preview (takes more time)
+
+ QFrame::NoFrame
-
-
- -
-
-
- Fix cut goes through the mandible twice
+
+ QFrame::Plain
+
+
-
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Plain
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Hard-update (use when normal update does not work correctly)
+
+
+ true
+
+
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Plain
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Lock updates to VSP
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+ -
+
+
+ Create 3D model of the reconstruction for 3D printing
+
+
+
+
-
-
+
- 0
- 0
+ 100
+ 100
@@ -465,36 +572,69 @@
QFrame::Plain
-
-
-
-
-
-
- 0
- 0
-
-
-
- Hard-update (use when normal update does not work correctly)
+
+
-
+
+
+ Show mandible planes interaction handles
-
- true
+
+
+ -
+
+
+ Show original mandible model
+
+
+ -
+
-
+ Show fibula segments lengths
+ -
+
+
+ 0
+
+
-
+
+
+ Lights rendering:
+
+
+
+ -
+
+
-
+
+ Lamp
+
+
+ -
+
+ Lamp and Shadows
+
+
+ -
+
+ MultiLamp
+
+
+ -
+
+ MultiLamp and Shadows
+
+
+
+
+
+
- -
-
-
- Create 3D model of the reconstruction for 3D printing
-
-
-
-
@@ -952,14 +1092,14 @@
- -
+
-
Miter box direction line
- -
+
-
false
@@ -1426,37 +1566,6 @@ Desing
- -
-
-
- Lights rendering:
-
-
-
- -
-
-
-
-
- Lamp
-
-
- -
-
- Lamp and Shadows
-
-
- -
-
- MultiLamp
-
-
- -
-
- MultiLamp and Shadows
-
-
-
-