Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixing global RenderingManager access from QmitkRenderWindowWidget and QmitkStdMultiWidget. #248

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

CFornari
Copy link

No description provided.

@kislinsk
Copy link
Contributor

kislinsk commented Jul 1, 2020

Hi, can you please explain your changes and why they are necessary? Thx!

edit: Nevermind, found your email on the mitk-users list. :-) However, there are some formatting issues and modified lines that go beyond the declared scope. Please check again to really narrow down this pull request to the absolutely necessary.

@CFornari
Copy link
Author

CFornari commented Jul 1, 2020

Hi, I reviewed the code and I believe all changes are needed to solve the global access to RenderingManager. Can you indicate which line is causing trouble?

I think an explanation in the changes made on QmitkRenderWindowWidget::RequestUpdate() and QmitkRenderWindowWidget::ForceImmediateUpdate() was lacking.

The original code had those lines:

void QmitkRenderWindowWidget::InitializeGUI()
{
  ...
  mitk::TimeGeometry::ConstPointer timeGeometry = m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll());
  mitk::RenderingManager::GetInstance()->InitializeViews(timeGeometry);
  ...
}

This sets m_DataStorage's geometry to all windows in the current application, here we have two problems:

  1. If m_DataStorage has no data loaded, the code will only mess up with all other rendering windows;
  2. If m_DataStorage has data loaded, the code will set the geometry from current data to all windows;

Different from QmitkStdMultiWidget where I moved the geometry initialization to QmitkStdMultiWidget::ResetCrosshair(), QmitkRenderWindowWidget has no reset method, to avoid any modification in the API, I moved the geometry initialization to QmitkRenderWindowWidget::RequestUpdate() and QmitkRenderWindowWidget::ForceImmediateUpdate().

Using QmitkRenderWindowWidget looks like this:

// Creating an Axial view.
QmitkRenderWindowWidget *renderWidget1 = new QmitkRenderWindowWidget(ui->left,QString("main"),ds1);
renderWidget1->GetRenderWindow()->SetLayoutIndex(mitk::BaseRenderer::ViewDirection::AXIAL);
renderWidget1->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial);
renderWidget1->GetRenderWindow()->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D);
renderWidget1->RequestUpdate();

NOTE: I have a minimal test application for the changes in the code, but I don't know how/where I should add to the project.

@CFornari
Copy link
Author

CFornari commented Jul 1, 2020

My original idea was to use QmitkRenderWindowWidget as a single axial window with mouse interaction. The first thing I noticed when using two widgets, was the global datastorage problem, which was solved with these changes.

But QmitkRenderWindowWidget is still lacking mouse interaction, decorations, methods for plane creation and a simple method for setting the view direction. I'm am actively working on a widget to solve all those problems, its already functional, I'm fixing minor bugs and I believe until next month, I will be able to make a PR and hear your comments.

@akalali
Copy link
Contributor

akalali commented Jul 7, 2020

So first of all thank you for your time and code suggestions. It is definitely worth taking a look at the different ways to initialize the view / geometry of the render windows.
However, I think there is some misunderstanding, looking at your last comment:

The QmitkRenderWindowWidget is an addition to and a wrapper around the QmitkRenderWindow. Its sole purpose is to add convenience-functions for the render window to allow to easily modify associated properties like decoration colors, background colors, corner annotations and crosshair.
The QmitkRenderWindowWidget is not supposed to take care of mouse interaction, plane create of view direction handling. All this can be done directly on the render window or is done inside one of the multi widgets (see QmitkAbstractMultiWidget, QmitkStdMultiWidget or QmitkMxNMultiWidget).

I will review your changes but in the meantime it might be useful to understand your use case and why you think it is necessary to extend the render window widget.

mitk::BaseRenderer::GetInstance(m_RenderWindow->GetRenderWindow())->SetDataStorage(dataStorage);
}
mitk::BaseRenderer::GetInstance(m_RenderWindow->GetRenderWindow())->SetDataStorage(dataStorage);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing changed here. Please don't change formatting.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the indentation, in my IDE everything looks normal.This happened after my push to github, I will see how to solve this formatting issue.

@@ -633,7 +637,7 @@ void QmitkStdMultiWidget::AddDisplayPlaneSubTree()
// ... of widget 1
mitk::BaseRenderer* renderer1 = mitk::BaseRenderer::GetInstance(GetRenderWindow1()->GetRenderWindow());
m_PlaneNode1 = renderer1->GetCurrentWorldPlaneGeometryNode();
m_PlaneNode1->SetProperty("visible", mitk::BoolProperty::New(true));
m_PlaneNode1->SetProperty("visible", mitk::BoolProperty::New(true));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing changed here. Please don't change formatting.

@@ -196,8 +198,8 @@ void QmitkRenderWindowWidget::InitializeGUI()

connect(m_RenderWindow, &QVTKOpenGLWidget::mouseEvent, this, &QmitkRenderWindowWidget::MouseEvent);

mitk::TimeGeometry::ConstPointer timeGeometry = m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll());
mitk::RenderingManager::GetInstance()->InitializeViews(timeGeometry);
mitk::BaseRenderer::GetInstance(m_RenderWindow->GetRenderWindow())->SetDataStorage(m_DataStorage);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree setting the data storage individually for the current render window is the correct way to do it (as it is done in QmitkRenderWindowWidget::SetDataStorage).

mitk::RenderingManager::GetInstance()->InitializeView(GetRenderWindow1()->GetRenderWindow(), geo);
mitk::RenderingManager::GetInstance()->InitializeView(GetRenderWindow2()->GetRenderWindow(), geo);
mitk::RenderingManager::GetInstance()->InitializeView(GetRenderWindow3()->GetRenderWindow(), geo);
mitk::RenderingManager::GetInstance()->InitializeView(GetRenderWindow4()->GetRenderWindow(), geo);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is your idea here? You are still initializing each render window to the same geometry, the bounding geometry of every data object in the data storage. This is what mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage); is actually supposed to do.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are displaying QmitkStdMultiWidget and QmitkRenderWindow both at the same time, each one rendering a different data set, mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage); would set the geometry from datastorage rendered by QmitkStdMultiWidget to QmitkRenderWindow, the last one may contain different data with different geometries. This is not a issue in MitkWorkbench because, usually, QmitkStdMultiWidget is the only active render widget.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you are explicitly initializing only the four render windows of the QmitkStdMultiWidget so that other render windows (that are registered with the global rendering manager) are not affected here.
I think that is reasonable and makes sense here.

@@ -742,7 +744,7 @@ void QmitkStdMultiWidget::CreateRenderWindowWidgets()
auto renderWindow2 = renderWindowWidget2->GetRenderWindow();
renderWindow2->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Sagittal);
renderWindowWidget2->SetDecorationColor(GetDecorationColor(1));
renderWindowWidget2->setStyleSheet("border: 0px");
// renderWindowWidget2->setStyleSheet("border: 0px");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove instead of commenting out.

@@ -196,8 +198,8 @@ void QmitkRenderWindowWidget::InitializeGUI()

connect(m_RenderWindow, &QVTKOpenGLWidget::mouseEvent, this, &QmitkRenderWindowWidget::MouseEvent);

mitk::TimeGeometry::ConstPointer timeGeometry = m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll());
mitk::RenderingManager::GetInstance()->InitializeViews(timeGeometry);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove this instead of using the code that you added in RequestUpdate and ForceImmediateUpdate:

auto geo = m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll());
mitk::RenderingManager::GetInstance()->InitializeView(m_RenderWindow->GetRenderWindow(), geo);

This will initialize the view for this specific render window.

Copy link
Author

@CFornari CFornari Jul 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we have two problems:

  1. mitk::RenderingManager::GetInstance()->InitializeViews(timeGeometry); has global scope, it creates the same problem that we have with:
    mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(dataStorage);
    See the example I described below. To avoid this I choose to use InitializeView() instead of InitializeViews().

  2. I moved the location to RequestUpdate and ForceImmediateUpdate, because in the case where data is loaded dynamically, lets say the user clicks an open file button, in this case m_DataStorage wouldn't have any data at QmitkRenderWidget's construction time, in which case computing the geometry from an empty m_DataStorage wouldn't be necessary. Maintaining this piece of code here is actually useful if the path to the data set is specified through command line or has been hardcoded.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm totally fine with 1.
I think 2. is a fix after changing the render window initialization of the QmitkStdMultiWidget: Here we do not re-initialize all render windows anymore but only the four render windows of the multi widget. So a single render window widget won't be affected. We need to be able to explicitly re-initialize a single render window widget, right?

Would it make sense to request an update inside InitializeGUI in case we actually do have some data loaded in the data storage?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to request an update inside InitializeGUI in case we actually do have some data loaded in the data storage?

Yes it will make sense, I will add a geometry initialization inside the function.

I think 2. is a fix after changing the render window initialization of the QmitkStdMultiWidget:

Actually I explicitly initialized the geometries inside QmitkStdMultiWidget, would you prefer a call to RequestUpdate instead of mitk::RenderingManager::GetInstance()->InitializeView(GetRenderWindow1()->GetRenderWindow(), geo);? The result will be the same.

Here we do not re-initialize all render windows anymore but only the four render windows of the multi widget. So a single render window widget won't be affected. We need to be able to explicitly re-initialize a single render window widget, right?

Yes this is the intention, although I ended up not calling RequesUpdate.

@@ -63,11 +63,15 @@ mitk::SliceNavigationController* QmitkRenderWindowWidget::GetSliceNavigationCont

void QmitkRenderWindowWidget::RequestUpdate()
{
auto geo = m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll());
mitk::RenderingManager::GetInstance()->InitializeView(m_RenderWindow->GetRenderWindow(), geo);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not put this inside the InitializeGUI-function?

mitk::RenderingManager::GetInstance()->RequestUpdate(m_RenderWindow->GetRenderWindow());
}

void QmitkRenderWindowWidget::ForceImmediateUpdate()
{
auto geo = m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll());
mitk::RenderingManager::GetInstance()->InitializeView(m_RenderWindow->GetRenderWindow(), geo);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not put this inside the InitializeGUI-function?

Copy link
Contributor

@akalali akalali left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you again.

We have an experimental version of a QmitkMxNMultiWidget that allows to have a more general set of render window widgets. After we included your PR it might be worth checking this widget again to see how it behaves with the changes concerning the view initialization of specific render window widgets.

@CFornari
Copy link
Author

Thanks for your patience.
I didn't knew about QmitkMxNMultiWidget I will take a look at it.

@akalali
Copy link
Contributor

akalali commented Sep 7, 2022

@CFornari
This has been on hold for looong time now but we are currently working on the mentioned QmitkMxNMultiWidget. While working on that / refactoring existing code we realized that some of the changes done here might be useful. I would like to include this pull request in our recent development.
However, since some times has passed, changes might be required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants