Page MenuHomePhabricator

[mxn multi widget] Re-initializations reset all render windows
Open, NormalPublic

Description

A re-init of the data nodes occurs often during a workflow. The mxn multi widget has some problems with that.
In a typical scenario the user opens a specific number of render windows, shows / hide certain data nodes of the storage to individually display different images. Maybe navigate individually in each render window (zoom, scroll).
If a reinit for all registered render windows is requested, this user defined preset will be reset to the node being reinitialized.

I propose to first gather different actions which lead to an update request.

Multi Widget (Editor)

  • changing the preferences page of the std- / mxn- multiwidgeteditor
    • QmitkStdMultiWidgetEditor::OnPreferencesChanged: mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(GetDataStorage());
    • QmitkMxNMultiWidgetEditor::OnPreferencesChanged: mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(GetDataStorage());

Segmentation Plugin

  • creating a new segmentation via the segmentation view
    • QmitkSegmentationView::CreateNewSegmentation: mitk::RenderingManager::GetInstance()->InitializeViews(referenceImage->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true); --> was already done in D523

MultiLabel-Segmentation Plugin

  • updating the UI controls after a different reference (node) / segmentation (node) has been selected in the plugin's node selectors
  • updating the UI controls after a layer has been deleted / changed
    • QmitkMultiLabelSegmentationView::UpdateControls --> was already done in D523
  • re-initializing the views after a new label has been created or after a different segmentation (node) has been selected in the plugin's node selector
    • QmitkMultiLabelSegmentationView::ReinitializeViews() --> was already done in D523 (ReinitializeViews() was removed)

Autocrop action

  • performing the autocrop action
    • QmitkAutocropAction::Run: mitk::RenderingManager::GetInstance()->InitializeViews(node->GetData()->GetTimeGeometry(), RenderingManager::REQUEST_UPDATE_ALL, true ); and mitk::RenderingManager::GetInstance()->RequestUpdateAll();

--> two request for the same thing (InitializeViews already performs a RequestUpdateAll) --> has partially been fixed with D542
--> Autocrop action should change the camera view. This is a feature which is more important than keeping the last camera position.

Possible solutions

  • allow locking specific render windows
  • only initialize certain render windows (active / selected, related to used node, ...)

Revisions and Commits

rMITK MITK
Restricted Differential Revision
Restricted Differential Revision

Event Timeline

kalali triaged this task as High priority.Jul 11 2019, 11:10 AM
kalali created this task.
kalali added a parent task: Restricted Maniphest Task.
  • creating a new segmentation via the segmentation view

Has been disabled for the BlackSwan Demo. A "re-initialize selected nodes" button has been added, which will reinitialize the geometry of both selected nodes only inside the currently active render window.

It is important to understand the differences between the following functions:

  • RenderingManager::RequestUpdateAll
    • basically goes through all the registered render windows and calls RenderingManager::RequestUpdate on each one
  • RenderingManager::RequestUpdate
    • sets the status of the given render window to "RENDERING_REQUESTED" and generates a rendering request event
    • QmitkRenderingManager::GenerateRenderingRequestEvent
      • this is an implementation of the abstract function which simply adds a QmitkRenderingRequestEvent to Qt's post event queue. If the event queue is processed and a QmitkRenderingRequestEvent::RenderingRequest is detected, RenderingManager::ExecutePendingRequests is called
    • RenderingManager::ExecutePendingRequests
      • goes through all the registered render windows and calls RenderingManager::ForceImmediateUpdate on each one that has the status "RENDERING_REQUESTED" set
    • RenderingManager::ForceImmediateUpdate
      • here the actual rendering is initiated by calling vtkWindow::Render on a given render window
  • BaseRenderer::RequestUpdate
    • basically calls RenderingManager::GetInstance()->RequestUpdate(this->m_RenderWindow); so as written above, the rendering of this specific render window is requested
  • IRenderWindowPart::RequestUpdate resp. QmitkAbstractMultiWidget::RequestUpdate
    • the latter is an implementation of the former (pure virtual function) and basically calls GetRenderingManager()->RequestUpdateAll(requestType), so as written above, the rendering of all the registered render windows is requested

All the functions above handle the (re-)rendering of the image but do not alter the view (camera angle / orientation, crosshair etc.).

  • RenderingManager::InitializeViews
    • different functions with this name (overloaded functions) are used to reset the view direction of a renderer's slice navigation controller or to call RenderingManager::InternalViewInitialization
  • RenderingManager::InitializeView
    • different functions with this name (overloaded functions) are used to reset the view direction of a renderer's slice navigation controller or to call RenderingManager::InternalViewInitialization
  • RenderingManager::InitializeViewsByBoundingObjects
    • using the data storage the bounding box of all relevant geometries is computed and used as geometry input to call RenderingManager::InitializeViews (see above)
  • RenderingManager::InternalViewInitialization
    • this private function is (as the name suggested) only called by the RenderingManager internally. This function resets the slice navigation controller and the camera controller of a given base renderer to reset the view. If a geometry was given this geometry will be used as world geometry for the slice navigation controller.

All InitializeView*-functions do not need anything from the RenderingManager except for the list / vector of render windows and the time navigation controller - both can be retrieved via public functions. I started separating the rendering functions from the view resetting functions to have two distinct classes with clearer responsibilities.

This gives me the following error log so it can easily be seen where these InitializeView*-functions are used (note: not all plugins are enabled so this is just a first batch of files to be changed):

Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_multilabelsegmentation	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.multilabelsegmentation\src\internal\QmitkMultiLabelSegmentationView.cpp	1090
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	MitkQtWidgets	C:\Development\MITK-dev\src\Modules\QtWidgets\src\QmitkStdMultiWidget.cpp	728
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	MitkQtWidgets	C:\Development\MITK-dev\src\Modules\QtWidgets\src\QmitkDataStorageTreeModel.cpp	348	
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_segmentation	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.segmentation\src\internal\QmitkSegmentationView.cpp	304	
Error	C2039	'InitializeViewsByBoundingObjects': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_stdmultiwidgeteditor	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.stdmultiwidgeteditor\src\QmitkStdMultiWidgetEditor.cpp	299	
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_segmentation	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.segmentation\src\internal\QmitkAutocropLabelSetImageAction.cpp	282	
Error	C2039	'InitializeViewsByBoundingObjects': is not a member of 'mitk::RenderingManager'	MitkQtWidgets	C:\Development\MITK-dev\src\Modules\QtWidgets\src\QmitkStdMultiWidget.cpp	230	
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	MitkQtWidgets	C:\Development\MITK-dev\src\Modules\QtWidgets\src\QmitkRenderWindowWidget.cpp	200	
Error	C2039	'InitializeViewsByBoundingObjects': is not a member of 'mitk::RenderingManager'	org_mitk_gui_common	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.common\src\mitkWorkbenchUtil.cpp	187	
Error	C2039	'InitializeViewsByBoundingObjects': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_mxnmultiwidgeteditor	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.mxnmultiwidgeteditor\src\QmitkMxNMultiWidgetEditor.cpp	177	
Error	C2039	'InitializeViewsByBoundingObjects': is not a member of 'mitk::RenderingManager'	MitkQtWidgets	C:\Development\MITK-dev\src\Modules\QtWidgets\src\QmitkMxNMultiWidget.cpp	162	
Error	C2039	'InitializeView': is not a member of 'mitk::RenderingManager'	MitkRenderWindowManager	C:\Development\MITK-dev\src\Modules\RenderWindowManager\src\mitkRenderWindowViewDirectionController.cpp	136	
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_ext	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.ext\src\internal\QmitkCommonExtPlugin.cpp	124	
Error	C2039	'InitializeView': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_application	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.application\src\QmitkDataNodeOpenInAction.cpp	105	
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_segmentation	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.segmentation\src\internal\QmitkAutocropAction.cpp	104	
Error	C2039	'InitializeView': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_application	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.application\src\QmitkDataNodeReinitAction.cpp	91	
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_application	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.application\src\QmitkDataNodeReinitAction.cpp	87	
Error	C2039	'InitializeView': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_application	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.application\src\QmitkDataNodeReinitAction.cpp	78	
Error (active)	E0135	class "mitk::RenderingManager" has no member "InitializeView"	org_mitk_gui_common	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.common\src\mitkIRenderingManager.cpp	74	
Error	C2039	'InitializeView': is not a member of 'mitk::RenderingManager'	org_mitk_gui_common	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.common\src\mitkIRenderingManager.cpp	74	
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_application	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.application\src\QmitkDataNodeReinitAction.cpp	74	
Error (active)	E0135	class "mitk::RenderingManager" has no member "InitializeViews"	org_mitk_gui_common	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.common\src\mitkIRenderingManager.cpp	68	
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	org_mitk_gui_common	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.common\src\mitkIRenderingManager.cpp	68	
Error (active)	E0135	class "mitk::RenderingManager" has no member "InitializeViews"	org_mitk_gui_common	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.common\src\mitkIRenderingManager.cpp	63	
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	org_mitk_gui_common	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.common\src\mitkIRenderingManager.cpp	63	
Error (active)	E0135	class "mitk::RenderingManager" has no member "InitializeViews"	org_mitk_gui_common	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.common\src\mitkIRenderingManager.cpp	57	
Error	C2039	'InitializeViews': is not a member of 'mitk::RenderingManager'	org_mitk_gui_common	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.common\src\mitkIRenderingManager.cpp	57	
Error	C2039	'InitializeViewsByBoundingObjects': is not a member of 'mitk::RenderingManager'	org_mitk_gui_qt_application	C:\Development\MITK-dev\src\Plugins\org.mitk.gui.qt.application\src\QmitkDataNodeGlobalReinitAction.cpp	39

I changed all occurrences of the InitializeView*-functions and built different MITK configurations to be sure not to miss anything.

There is a problem though: Three classes (QmitkUltrasoundSupport, QmitkDataManagerLightView, QmitkUSNavigationMarkerPlacement) do not access the global rendering manager but rather retrieve the relevant rendering manager from the renderWindowPart (which is a IRenderWindowPart) by calling QmitkAbstractView::GetRenderWindowPart. The problem is that the returned IRenderWindowPart does not allow to retrieve a rendering manager but only an IRenderingManager. However, the IRenderingManager does not provide all functions, as its intent is to hiding some methods from the user. This leads to a problem because I need to pass a RenderingManager to the InitializeView*-functions, but only have an IRenderingManager.

My question to @floca, @kislinsk: What is the purpose of this class and do you find it useful? I don't see a real value in adding this Interface (which in my opinion is not really an Interface) but rather add some unnecessary complexity.
The function MakeRenderingManagerInterface is only used inside two classes, QmitkAbstractRenderEditor and SimpleRenderWindowView and I don't see why we cannot directly use a RenderingManager here.

I cannot answer that question directly. As I do not know the history of this class and documentation does not help. Maybe @nolden does.

But nevertheless I would not mix those two topics. For the this task I would modify IRenderWindowPart to the point that it does not hinder this task.
The question of IRenderingManger is needed or how the overall design could be improved, i would move this to a new task, we can sort out later.

My 2 cents.

The point is: I'm removing the InitializeView*-functions from the RenderingManager to separate the repsonsibilities. For these functions to work I now want to pass the RenderingManager as an argument - but this is not working with an IRenderingManager, which I get returned by the mentioned classes.

So I guess my real question here is: Regardless of the IRenderingManager: Is there any need for
QmitkAbstractRenderEditor and SimpleRenderWindowView to use code like

m_RenderingManager(mitk::MakeRenderingManagerInterface(mitk::RenderingManager::GetInstance()))

instead of just using

m_RenderingManagerInterface(mitk::RenderingManager::GetInstance())

From what I see, using the first variant only makes the mentioned classes use an IRenderingManager which hides some functions from the user / developer inside this class.

I have already tried separating and removing some stuff so maybe I'll just open a review and we can discuss things there.

Oh and btw.: I truly mixing some things here, as this is a bigger issue which also tackles other tasks (such as T26496: [mxn multi widget] Re-initializations reset all render windows and T27613: Improve reinit behavior) so the description does not perfectly fit what I'm currently doing.

kalali added a revision: Restricted Differential Revision.Jul 5 2021, 6:05 PM
kalali removed a subscriber: nolden.
kalali lowered the priority of this task from High to Normal.Mon, Sep 6, 2:37 PM

I edited the task description since most of the issues do not occur anymore, due to the changed introduced by D523.
However, the general problem remains: It is not possible to re-initialize / reset the view and camera of individual render windows which is important for the MxNMultiWidget in order to fully unleash its potential.

kalali added a revision: Restricted Differential Revision.Tue, Sep 7, 8:19 AM
kalali added a revision: Restricted Differential Revision.Tue, Sep 7, 9:17 AM
kalali updated the task description. (Show Details)