diff --git a/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp b/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp index e10c4b2282..aedf8ae4ed 100644 --- a/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp +++ b/Modules/Core/TestingHelper/src/mitkInteractionTestHelper.cpp @@ -1,436 +1,436 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // MITK #include #include #include #include #include // VTK #include #include // us #include #include mitk::InteractionTestHelper::InteractionTestHelper(const std::string &interactionXmlFilePath) : m_InteractionFilePath(interactionXmlFilePath) { this->Initialize(interactionXmlFilePath); } void mitk::InteractionTestHelper::Initialize(const std::string &interactionXmlFilePath) { tinyxml2::XMLDocument document; if (tinyxml2::XML_SUCCESS == document.LoadFile(interactionXmlFilePath.c_str())) { // get RenderingManager instance auto rm = mitk::RenderingManager::GetInstance(); // create data storage m_DataStorage = mitk::StandaloneDataStorage::New(); // for each renderer found create a render window and configure for (auto *element = document.FirstChildElement(mitk::InteractionEventConst::xmlTagInteractions().c_str()) ->FirstChildElement(mitk::InteractionEventConst::xmlTagConfigRoot().c_str()) ->FirstChildElement(mitk::InteractionEventConst::xmlTagRenderer().c_str()); element != nullptr; element = element->NextSiblingElement(mitk::InteractionEventConst::xmlTagRenderer().c_str())) { // get name of renderer const char *rendererName = element->Attribute(mitk::InteractionEventConst::xmlEventPropertyRendererName().c_str()); // get view direction mitk::SliceNavigationController::ViewDirection viewDirection = mitk::SliceNavigationController::Axial; if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyViewDirection().c_str()) != nullptr) { int viewDirectionNum = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyViewDirection().c_str())); viewDirection = static_cast(viewDirectionNum); } // get mapper slot id - mitk::BaseRenderer::MapperSlotId mapperID = mitk::BaseRenderer::Standard2D; + MapperSlotId mapperID = mitk::BaseRenderer::Standard2D; if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str()) != nullptr) { int mapperIDNum = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str())); - mapperID = static_cast(mapperIDNum); + mapperID = static_cast(mapperIDNum); } // Get Size of Render Windows int size[3]; size[0] = size[1] = size[2] = 0; if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeX().c_str()) != nullptr) { size[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeX().c_str())); } if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeY().c_str()) != nullptr) { size[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeY().c_str())); } if (element->Attribute(mitk::InteractionEventConst::xmlRenderSizeZ().c_str()) != nullptr) { size[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlRenderSizeZ().c_str())); } // create renderWindow, renderer and dispatcher auto rw = RenderWindow::New(nullptr, rendererName); // VtkRenderWindow is created within constructor if nullptr if (size[0] != 0 && size[1] != 0) { rw->SetSize(size[0], size[1]); rw->GetRenderer()->Resize(size[0], size[1]); } // set storage of renderer rw->GetRenderer()->SetDataStorage(m_DataStorage); // set view direction to axial rw->GetSliceNavigationController()->SetDefaultViewDirection(viewDirection); // set renderer to render 2D rw->GetRenderer()->SetMapperID(mapperID); rw->GetRenderer()->PrepareRender(); // Some more magic for the 3D render window case: // Camera view direction, position and focal point if (mapperID == mitk::BaseRenderer::Standard3D) { if (element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str()) != nullptr) { double cameraFocalPoint[3]; cameraFocalPoint[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str())); cameraFocalPoint[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointY().c_str())); cameraFocalPoint[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointZ().c_str())); rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetFocalPoint(cameraFocalPoint); } if (element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str()) != nullptr) { double cameraPosition[3]; cameraPosition[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str())); cameraPosition[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionY().c_str())); cameraPosition[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionZ().c_str())); rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetPosition(cameraPosition); } if (element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str()) != nullptr) { double viewUp[3]; viewUp[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str())); viewUp[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpY().c_str())); viewUp[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpZ().c_str())); rw->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetViewUp(viewUp); } } rw->GetVtkRenderWindow()->Render(); rw->GetVtkRenderWindow()->WaitForCompletion(); // connect SliceNavigationControllers to timestep changed event of TimeNavigationController rw->GetSliceNavigationController()->ConnectGeometryTimeEvent(rm->GetTimeNavigationController()); rm->GetTimeNavigationController()->ConnectGeometryTimeEvent(rw->GetSliceNavigationController()); // add to list of known render windows m_RenderWindowList.push_back(rw); } // TODO: check the following lines taken from QmitkStdMultiWidget and adapt them to be executed in our code here. // mitkWidget1->GetSliceNavigationController() // ->ConnectGeometrySendEvent(mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())); // register interaction event obserer to handle scroll events InitializeDisplayActionEventHandling(); } else { mitkThrow() << "Can not load interaction xml file <" << m_InteractionFilePath << ">"; } // WARNING assumes a 3D window exists !!!! this->AddDisplayPlaneSubTree(); } void mitk::InteractionTestHelper::InitializeDisplayActionEventHandling() { m_DisplayActionEventBroadcast = mitk::DisplayActionEventBroadcast::New(); m_DisplayActionEventBroadcast->LoadStateMachine("DisplayInteraction.xml"); m_DisplayActionEventBroadcast->SetEventConfig("DisplayConfigMITKBase.xml"); m_DisplayActionEventBroadcast->AddEventConfig("DisplayConfigCrosshair.xml"); } mitk::InteractionTestHelper::~InteractionTestHelper() { mitk::RenderingManager *rm = mitk::RenderingManager::GetInstance(); // unregister renderers auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { rm->GetTimeNavigationController()->Disconnect((*it)->GetSliceNavigationController()); (*it)->GetSliceNavigationController()->Disconnect(rm->GetTimeNavigationController()); mitk::BaseRenderer::RemoveInstance((*it)->GetVtkRenderWindow()); } rm->RemoveAllObservers(); } mitk::DataStorage::Pointer mitk::InteractionTestHelper::GetDataStorage() { return m_DataStorage; } void mitk::InteractionTestHelper::AddNodeToStorage(mitk::DataNode::Pointer node) { this->m_DataStorage->Add(node); this->Set3dCameraSettings(); } void mitk::InteractionTestHelper::PlaybackInteraction() { mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); // load events if not loaded yet if (m_Events.empty()) this->LoadInteraction(); auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { (*it)->GetRenderer()->PrepareRender(); (*it)->GetVtkRenderWindow()->Render(); (*it)->GetVtkRenderWindow()->WaitForCompletion(); } mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); it = m_RenderWindowList.begin(); for (; it != end; ++it) { (*it)->GetVtkRenderWindow()->Render(); (*it)->GetVtkRenderWindow()->WaitForCompletion(); } // mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); // playback all events in queue for (unsigned long i = 0; i < m_Events.size(); ++i) { // let dispatcher of sending renderer process the event m_Events.at(i)->GetSender()->GetDispatcher()->ProcessEvent(m_Events.at(i)); } if (false) { it--; (*it)->GetVtkRenderWindow()->GetInteractor()->Start(); } } void mitk::InteractionTestHelper::LoadInteraction() { // load interaction pattern from xml file std::ifstream xmlStream(m_InteractionFilePath.c_str()); mitk::XML2EventParser parser(xmlStream); m_Events = parser.GetInteractions(); xmlStream.close(); // Avoid VTK warning: Trying to delete object with non-zero reference count. parser.SetReferenceCount(0); } void mitk::InteractionTestHelper::SetTimeStep(int newTimeStep) { mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(m_DataStorage); bool timeStepIsvalid = mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetCreatedWorldGeometry()->IsValidTimeStep( newTimeStep); if (timeStepIsvalid) { mitk::RenderingManager::GetInstance()->GetTimeNavigationController()->GetTime()->SetPos(newTimeStep); } } mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindowByName(const std::string &name) { auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { if (name.compare((*it)->GetRenderer()->GetName()) == 0) return (*it).GetPointer(); } return nullptr; } mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindowByDefaultViewDirection( mitk::SliceNavigationController::ViewDirection viewDirection) { auto it = m_RenderWindowList.begin(); auto end = m_RenderWindowList.end(); for (; it != end; ++it) { if (viewDirection == (*it)->GetSliceNavigationController()->GetDefaultViewDirection()) return (*it).GetPointer(); } return nullptr; } mitk::RenderWindow *mitk::InteractionTestHelper::GetRenderWindow(unsigned int index) { if (index < m_RenderWindowList.size()) { return m_RenderWindowList.at(index).GetPointer(); } else { return nullptr; } } void mitk::InteractionTestHelper::AddDisplayPlaneSubTree() { // add the displayed planes of the multiwidget to a node to which the subtree // @a planesSubTree points ... mitk::PlaneGeometryDataMapper2D::Pointer mapper; mitk::IntProperty::Pointer layer = mitk::IntProperty::New(1000); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetProperty("name", mitk::StringProperty::New("Widgets")); node->SetProperty("helper object", mitk::BoolProperty::New(true)); m_DataStorage->Add(node); for (auto it : m_RenderWindowList) { if (it->GetRenderer()->GetMapperID() == BaseRenderer::Standard3D) continue; // ... of widget 1 mitk::DataNode::Pointer planeNode1 = (mitk::BaseRenderer::GetInstance(it->GetVtkRenderWindow()))->GetCurrentWorldPlaneGeometryNode(); planeNode1->SetProperty("visible", mitk::BoolProperty::New(true)); planeNode1->SetProperty("name", mitk::StringProperty::New("widget1Plane")); planeNode1->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); planeNode1->SetProperty("helper object", mitk::BoolProperty::New(true)); planeNode1->SetProperty("layer", layer); planeNode1->SetColor(1.0, 0.0, 0.0); mapper = mitk::PlaneGeometryDataMapper2D::New(); planeNode1->SetMapper(mitk::BaseRenderer::Standard2D, mapper); m_DataStorage->Add(planeNode1, node); } } void mitk::InteractionTestHelper::Set3dCameraSettings() { tinyxml2::XMLDocument document; if (tinyxml2::XML_SUCCESS == document.LoadFile(m_InteractionFilePath.c_str())) { // for each renderer found create a render window and configure for (auto *element = document.FirstChildElement(mitk::InteractionEventConst::xmlTagInteractions().c_str()) ->FirstChildElement(mitk::InteractionEventConst::xmlTagConfigRoot().c_str()) ->FirstChildElement(mitk::InteractionEventConst::xmlTagRenderer().c_str()); element != nullptr; element = element->NextSiblingElement(mitk::InteractionEventConst::xmlTagRenderer().c_str())) { // get name of renderer const char *rendererName = element->Attribute(mitk::InteractionEventConst::xmlEventPropertyRendererName().c_str()); // get mapper slot id - mitk::BaseRenderer::MapperSlotId mapperID = mitk::BaseRenderer::Standard2D; + MapperSlotId mapperID = mitk::BaseRenderer::Standard2D; if (element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str()) != nullptr) { int mapperIDNum = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlEventPropertyMapperID().c_str())); - mapperID = static_cast(mapperIDNum); + mapperID = static_cast(mapperIDNum); } if (mapperID == mitk::BaseRenderer::Standard3D) { RenderWindow *namedRenderer = nullptr; for (const auto &it : m_RenderWindowList) { if (strcmp(it->GetRenderer()->GetName(), rendererName) == 0) { namedRenderer = it.GetPointer(); break; } } if (namedRenderer == nullptr) { MITK_ERROR << "No match for render window was found."; return; } namedRenderer->GetRenderer()->PrepareRender(); if (element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str()) != nullptr) { double cameraFocalPoint[3]; cameraFocalPoint[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointX().c_str())); cameraFocalPoint[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointY().c_str())); cameraFocalPoint[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraFocalPointZ().c_str())); namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetFocalPoint(cameraFocalPoint); } if (element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str()) != nullptr) { double cameraPosition[3]; cameraPosition[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionX().c_str())); cameraPosition[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionY().c_str())); cameraPosition[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlCameraPositionZ().c_str())); namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetPosition(cameraPosition); } if (element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str()) != nullptr) { double viewUp[3]; viewUp[0] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpX().c_str())); viewUp[1] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpY().c_str())); viewUp[2] = std::atoi(element->Attribute(mitk::InteractionEventConst::xmlViewUpZ().c_str())); namedRenderer->GetRenderer()->GetVtkRenderer()->GetActiveCamera()->SetViewUp(viewUp); } namedRenderer->GetVtkRenderWindow()->Render(); } } } } diff --git a/Modules/Core/include/mitkBaseRenderer.h b/Modules/Core/include/mitkBaseRenderer.h index 5d08a5b9e5..d91f6a2b13 100644 --- a/Modules/Core/include/mitkBaseRenderer.h +++ b/Modules/Core/include/mitkBaseRenderer.h @@ -1,433 +1,467 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef MITKBASERENDERER_H #define MITKBASERENDERER_H -#include "mitkCameraRotationController.h" #include "mitkDataStorage.h" #include "mitkPlaneGeometry.h" #include "mitkPlaneGeometryData.h" -#include "mitkSliceNavigationController.h" #include "mitkTimeGeometry.h" +#include "mitkCameraController.h" +#include "mitkCameraRotationController.h" +#include "mitkSliceNavigationController.h" + #include "mitkBindDispatcherInteractor.h" #include "mitkDispatcher.h" #include #include #include #include namespace mitk { - class NavigationController; - class SliceNavigationController; - class CameraRotationController; - class CameraController; - class DataStorage; class Mapper; class BaseLocalStorageHandler; - class KeyEvent; #pragma GCC visibility push(default) itkEventMacroDeclaration(RendererResetEvent, itk::AnyEvent); #pragma GCC visibility pop - //## @brief Organizes the rendering process - //## - //## Organizes the rendering process. A Renderer contains a reference to a - //## DataStorage and asks the mappers of the data objects to render - //## the data into the renderwindow it is associated to. - //## - //## \#Render() checks if rendering is currently allowed by calling - //## RenderWindow::PrepareRendering(). Initialization of a rendering context - //## can also be performed in this method. - //## - //## The actual rendering code has been moved to \#Repaint() - //## Both \#Repaint() and \#Update() are declared protected now. - //## - //## Note: Separation of the Repaint and Update processes (rendering vs - //## creating a vtk prop tree) still needs to be worked on. The whole - //## rendering process also should be reworked to use VTK based classes for - //## both 2D and 3D rendering. - //## @ingroup Renderer + /* + * \brief Organizes the rendering process + * + * A BaseRenderer contains a reference to a given vtkRenderWindow + * and a corresponding vtkRenderer. + * The BaseRenderer defines which mapper should be used (2D / 3D) + * and which view direction should be rendered. + * + * All existing BaseRenderer are stored in a static variable + * that can be accessed / modified via the static functions. + * VtkPropRenderer is a concrete implementation of a BaseRenderer. + */ class MITKCORE_EXPORT BaseRenderer : public itk::Object { public: - typedef std::map BaseRendererMapType; + + typedef std::map BaseRendererMapType; static BaseRendererMapType baseRendererMap; - static BaseRenderer *GetInstance(vtkRenderWindow *renWin); - static void AddInstance(vtkRenderWindow *renWin, BaseRenderer *baseRenderer); - static void RemoveInstance(vtkRenderWindow *renWin); + static BaseRenderer* GetInstance(vtkRenderWindow* renderWindow); + static void AddInstance(vtkRenderWindow* renderWindow, BaseRenderer* baseRenderer); + static void RemoveInstance(vtkRenderWindow* renderWindow); - static BaseRenderer *GetByName(const std::string &name); - static vtkRenderWindow *GetRenderWindowByName(const std::string &name); + static BaseRenderer* GetByName(const std::string& name); + static vtkRenderWindow* GetRenderWindowByName(const std::string& name); - /** Standard class typedefs. */ mitkClassMacroItkParent(BaseRenderer, itk::Object); - BaseRenderer(const char *name = nullptr, vtkRenderWindow *renWin = nullptr); - - //## @brief MapperSlotId defines which kind of mapper (e.g. 2D or 3D) should be used. - typedef int MapperSlotId; + BaseRenderer(const char* name = nullptr, vtkRenderWindow* renderWindow = nullptr); + /** + * \brief Defines which kind of mapper (e.g. 2D or 3D) should be used. + */ enum StandardMapperSlot { Standard2D = 1, Standard3D = 2 }; - //## @brief Possible view directions for render windows. + /** + * \brief Defines which view direction should be rendered. + */ enum class ViewDirection { AXIAL = 0, SAGITTAL, CORONAL, THREE_D }; void RemoveAllLocalStorages(); - void RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler* lsh); - void UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler* lsh); - - virtual void SetDataStorage(DataStorage *storage); - - //## return the DataStorage that is used for rendering - virtual DataStorage::Pointer GetDataStorage() const { return m_DataStorage.GetPointer(); } + void RegisterLocalStorageHandler(BaseLocalStorageHandler* lsh); + void UnregisterLocalStorageHandler(BaseLocalStorageHandler* lsh); - //## @brief Access the RenderWindow into which this renderer renders. - vtkRenderWindow *GetRenderWindow() const { return m_RenderWindow; } - vtkRenderer *GetVtkRenderer() const { return m_VtkRenderer; } + virtual void SetDataStorage(DataStorage* storage); - //## @brief Returns the Dispatcher which handles Events for this BaseRenderer - Dispatcher::Pointer GetDispatcher() const; + virtual DataStorage::Pointer GetDataStorage() const + { + return m_DataStorage.GetPointer(); + } - //## @brief Default mapper id to use. - static const MapperSlotId defaultMapper; + vtkRenderWindow* GetRenderWindow() const + { + return m_RenderWindow; + } - //## @brief Do the rendering and flush the result. - virtual void Paint(); + vtkRenderer* GetVtkRenderer() const + { + return m_VtkRenderer; + } - //## @brief Initialize the RenderWindow. Should only be called from RenderWindow. - virtual void Initialize(); + /** + * \brief Get the dispatcher, which handles events for this base renderer. + */ + Dispatcher::Pointer GetDispatcher() const; - //## @brief Called to inform the renderer that the RenderWindow has been resized. + /** + * \brief Set a new size for the render window. + */ virtual void Resize(int w, int h); - //## @brief Initialize the renderer with a RenderWindow (@a renderwindow). - virtual void InitRenderer(vtkRenderWindow *renderwindow); + /** + * \brief Initialize the base renderer with a vtk render window. + * Set the new renderer for the camera controller. + */ + virtual void InitRenderer(vtkRenderWindow* renderwindow); - //## @brief Set the initial size. Called by RenderWindow after it has become - //## visible for the first time. + /** + * \brief Set the initial size for the render window. + */ virtual void InitSize(int w, int h); - //## @brief Draws a point on the widget. - //## Should be used during conferences to show the position of the remote mouse - virtual void DrawOverlayMouse(Point2D &p2d); - - //## @brief Set/Get the WorldGeometry (m_WorldGeometry) for 3D and 2D rendering, that describing the - //## (maximal) area to be rendered. - //## - //## Depending of the type of the passed BaseGeometry more or less information can be extracted: - //## \li if it is a PlaneGeometry (which is a sub-class of BaseGeometry), m_CurrentWorldPlaneGeometry is - //## also set to point to it. m_WorldTimeGeometry is set to nullptr. - //## \li if it is a TimeGeometry, m_WorldTimeGeometry is also set to point to it. - //## If m_WorldTimeGeometry contains instances of SlicedGeometry3D, m_CurrentWorldPlaneGeometry is set to - //## one of geometries stored in the SlicedGeometry3D according to the value of m_Slice; otherwise - //## a PlaneGeometry describing the top of the bounding-box of the BaseGeometry is set as the - //## m_CurrentWorldPlaneGeometry. - //## \li otherwise a PlaneGeometry describing the top of the bounding-box of the BaseGeometry - //## is set as the m_CurrentWorldPlaneGeometry. m_WorldTimeGeometry is set to nullptr. - //## @todo add calculation of PlaneGeometry describing the top of the bounding-box of the BaseGeometry - //## when the passed BaseGeometry is not sliced. - //## \sa m_WorldGeometry - //## \sa m_WorldTimeGeometry - //## \sa m_CurrentWorldPlaneGeometry - virtual void SetWorldGeometry3D(const BaseGeometry *geometry); - virtual void SetWorldTimeGeometry(const mitk::TimeGeometry *geometry); + virtual void DrawOverlayMouse(Point2D&) + { + MITK_INFO << "BaseRenderer::DrawOverlayMouse() should be in concret implementation OpenGLRenderer." << std::endl; + } + /** + * \brief Set the world time geometry using the given TimeGeometry. + * + * Setting a new world time geometry updates the current world geometry and the + * curent world plane geometry, using the currently selected slice and timestep. + */ + virtual void SetWorldTimeGeometry(const mitk::TimeGeometry* geometry); itkGetConstObjectMacro(WorldTimeGeometry, TimeGeometry); - //## @brief Get the current 3D-worldgeometry (m_CurrentWorldGeometry) used for 3D-rendering + /** + * \brief Get the current time-extracted 3D-geometry. + */ itkGetConstObjectMacro(CurrentWorldGeometry, BaseGeometry); - //## @brief Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering - itkGetConstObjectMacro(CurrentWorldPlaneGeometry, PlaneGeometry) + /** + * \brief Get the current slice-extracted 2D-geometry. + */ + itkGetConstObjectMacro(CurrentWorldPlaneGeometry, PlaneGeometry); - //## Calculates the bounds of the DataStorage (if it contains any valid data), - //## creates a geometry from these bounds and sets it as world geometry of the renderer. - //## - //## Call this method to re-initialize the renderer to the current DataStorage - //## (e.g. after loading an additional dataset), to ensure that the view is - //## aligned correctly. - //## \warning This is not implemented yet. - virtual bool SetWorldGeometryToDataStorageBounds() { return false; } + virtual bool SetWorldGeometryToDataStorageBounds() + { + return false; + } - //## @brief Set/Get m_Slice which defines together with m_TimeStep the 2D geometry - //## stored in m_WorldTimeGeometry used as m_CurrentWorldPlaneGeometry + /** + * \brief Set the slice that should be used for geometry extraction. + * + * The slice defines the current slice-extracted 2D-geometry (CurrentWorldPlaneGeometry). + * Setting a new slice will update the current world geometry and the + * curent world plane geometry. + */ virtual void SetSlice(unsigned int slice); itkGetConstMacro(Slice, unsigned int); - //## @brief Set/Get m_TimeStep which defines together with m_Slice the 2D geometry - //## stored in m_WorldTimeGeometry used as m_CurrentWorldPlaneGeometry + /** + * \brief Set the timestep that should be used for geometry extraction. + * + * The timestep defines the current time-extracted 3D-geometry (CurrentWorldGeometry). + * Setting a new timestep will update the current world geometry and the + * curent world plane geometry. + */ virtual void SetTimeStep(unsigned int timeStep); itkGetConstMacro(TimeStep, unsigned int); - //## @brief Get the time-step of a BaseData object which - //## exists at the time of the currently displayed content - //## - //## Returns -1 or mitk::BaseData::m_TimeSteps if there - //## is no data at the current time. - TimeStepType GetTimeStep(const BaseData *data) const; - - //## @brief Get the time in ms of the currently displayed content - //## + /** + * \brief Get the timestep of a BaseData object which + * exists at the time of the currently displayed content. + * + * Returns -1 if there is no data at the current time. + */ + TimeStepType GetTimeStep(const BaseData* data) const; + + /** + * \brief Get the time in ms of the currently display content (geometry). + */ ScalarType GetTime() const; - //## @brief SetWorldGeometry is called according to the geometrySliceEvent, - //## which is supposed to be a SliceNavigationController::GeometrySendEvent - virtual void SetGeometry(const itk::EventObject &geometrySliceEvent); - - //## @brief UpdateWorldGeometry is called to re-read the 2D geometry from the - //## slice navigation controller - virtual void UpdateGeometry(const itk::EventObject &geometrySliceEvent); - - //## @brief SetSlice is called according to the geometrySliceEvent, - //## which is supposed to be a SliceNavigationController::GeometrySliceEvent - virtual void SetGeometrySlice(const itk::EventObject &geometrySliceEvent); - - //## @brief SetTimeStep is called according to the geometrySliceEvent, - //## which is supposed to be a SliceNavigationController::GeometryTimeEvent - virtual void SetGeometryTime(const itk::EventObject &geometryTimeEvent); - - //## @brief Get a DataNode pointing to a data object containing the current 2D-worldgeometry - // m_CurrentWorldPlaneGeometry (for 2D rendering) - itkGetObjectMacro(CurrentWorldPlaneGeometryNode, DataNode) - - //## @brief Sets timestamp of CurrentWorldPlaneGeometry and forces so reslicing in that renderwindow + /** + * \brief Set the world time geometry using the geometry of the given event. + * + * The function is triggered by a SliceNavigationController::GeometrySendEvent. + */ + virtual void SetGeometry(const itk::EventObject& geometrySliceEvent); + + /** + * \brief Set the current world plane geometry using the existing current world geometry. + * + * The function is triggered by a SliceNavigationController::GeometryUpdateEvent. + */ + virtual void UpdateGeometry(const itk::EventObject& geometrySliceEvent); + + /** + * \brief Set the current slice using "SetSlice" and update the current world geometry + * and the current world plane geometry. + * + * The function is triggered by a SliceNavigationController::GeometrySliceEvent. + */ + virtual void SetGeometrySlice(const itk::EventObject& geometrySliceEvent); + + /** + * \brief Set the current time using "SetTimeStep" and update the current world geometry + * and the current world plane geometry. + * + * The function is triggered by a TimeNavigationController::TimeEvent. + */ + virtual void SetGeometryTime(const itk::EventObject& geometryTimeEvent); + + itkGetObjectMacro(CurrentWorldPlaneGeometryNode, DataNode); + + /** + * \brief Modify the update time of the current world plane geometry and force reslicing. + */ void SendUpdateSlice(); - //## @brief Get timestamp of last call of SetCurrentWorldPlaneGeometry + /** + * \brief Get timestamp of the update time of the current world plane geometry. + */ itkGetMacro(CurrentWorldPlaneGeometryUpdateTime, unsigned long); - //## @brief Get timestamp of last change of current TimeStep + /** + * \brief Get timestamp of the update time of the current timestep. + */ itkGetMacro(TimeStepUpdateTime, unsigned long); - //## @brief Perform a picking: find the x,y,z world coordinate of a - //## display x,y coordinate. - //## @warning Has to be overwritten in subclasses for the 3D-case. - //## - //## Implemented here only for 2D-rendering - virtual void PickWorldPoint(const Point2D &diplayPosition, Point3D &worldPosition) const = 0; - - /** \brief Determines the object (mitk::DataNode) closest to the current - * position by means of picking - * - * \warning Implementation currently empty for 2D rendering; intended to be - * implemented for 3D renderers */ - virtual DataNode *PickObject(const Point2D & /*displayPosition*/, Point3D & /*worldPosition*/) const + /** + * \brief Pick a world coordinate (x,y,z) given a display coordinate (x,y). + * + * \warning Not implemented; has to be overwritten in subclasses. + */ + virtual void PickWorldPoint(const Point2D& diplayPosition, Point3D& worldPosition) const = 0; + + /** + * \brief Determines the object (mitk::DataNode) closest to the current + * position by means of picking. + * + * \warning Implementation currently empty for 2D rendering; intended to be + * implemented for 3D renderers. + */ + virtual DataNode* PickObject(const Point2D& /*displayPosition*/, Point3D& /*worldPosition*/) const { return nullptr; } - //## @brief Get the MapperSlotId to use. + /** + * \brief Get the currently used mapperID. + */ itkGetMacro(MapperID, MapperSlotId); itkGetConstMacro(MapperID, MapperSlotId); - //## @brief Set the MapperSlotId to use. + /** + * \brief Set the used mapperID. + */ virtual void SetMapperID(MapperSlotId id); - virtual int *GetSize() const; - virtual int *GetViewportSize() const; + virtual int* GetSize() const; + virtual int* GetViewportSize() const; - void SetSliceNavigationController(SliceNavigationController *SlicenavigationController); + void SetSliceNavigationController(SliceNavigationController* SlicenavigationController); itkGetObjectMacro(CameraController, CameraController); itkGetObjectMacro(SliceNavigationController, SliceNavigationController); itkGetObjectMacro(CameraRotationController, CameraRotationController); itkGetMacro(EmptyWorldGeometry, bool); - //## @brief Tells if the displayed region is shifted and rescaled if the render window is resized. - itkGetMacro(KeepDisplayedRegion, bool) - - //## @brief Tells if the displayed region should be shifted and rescaled if the render window is resized. + /** + * \brief Getter/Setter for defining if the displayed region should be shifted + * or rescaled if the render window is resized. + */ + itkGetMacro(KeepDisplayedRegion, bool); itkSetMacro(KeepDisplayedRegion, bool); - //## @brief get the name of the Renderer - //## @note - const char *GetName() const + /** + * \brief Return the name of the base renderer + */ + const char* GetName() const { return m_Name.c_str(); } - //## @brief get the x_size of the RendererWindow - //## @note - int GetSizeX() const { return GetSize()[0]; } + /** + * \brief Return the size in x-direction of the base renderer. + */ + int GetSizeX() const + { + return this->GetSize()[0]; + } + + /** + * \brief Return the size in y-direction of the base renderer. + */ + int GetSizeY() const + { + return this->GetSize()[1]; + } - //## @brief get the y_size of the RendererWindow - //## @note - int GetSizeY() const { return GetSize()[1]; } - const double *GetBounds() const; + /** + * \brief Return the bounds of the bounding box of the + * current world geometry (time-extracted 3D-geometry). + * + * If the geometry is empty, the bounds are set to zero. + */ + const double* GetBounds() const; void RequestUpdate(); void ForceImmediateUpdate(); - /** Returns number of mappers which are visible and have level-of-detail - * rendering enabled */ + /** + * \brief Return the number of mappers which are visible and have + * level-of-detail rendering enabled. + */ unsigned int GetNumberOfVisibleLODEnabledMappers() const; - //## @brief This method converts a display point to the 3D world index - //## using the geometry of the renderWindow. - void DisplayToWorld(const Point2D &displayPoint, Point3D &worldIndex) const; - - //## @brief This method converts a display point to the 2D world index, mapped onto the display plane - //## using the geometry of the renderWindow. - void DisplayToPlane(const Point2D &displayPoint, Point2D &planePointInMM) const; - - //## @brief This method converts a 3D world index to the display point - //## using the geometry of the renderWindow. - void WorldToDisplay(const Point3D &worldIndex, Point2D &displayPoint) const; - - //## @brief This method converts a 3D world index to the point on the viewport - //## using the geometry of the renderWindow. - void WorldToView(const Point3D &worldIndex, Point2D &viewPoint) const; - - //## @brief This method converts a 2D plane coordinate to the display point - //## using the geometry of the renderWindow. - void PlaneToDisplay(const Point2D &planePointInMM, Point2D &displayPoint) const; - - //## @brief This method converts a 2D plane coordinate to the point on the viewport - //## using the geometry of the renderWindow. - void PlaneToView(const Point2D &planePointInMM, Point2D &viewPoint) const; + /** + * \brief Convert a display point to the 3D world index + * using the geometry of the renderWindow. + */ + void DisplayToWorld(const Point2D& displayPoint, Point3D& worldIndex) const; + + /** + * \brief Convert a display point to the 2D world index, mapped onto the display plane + * using the geometry of the renderWindow. + */ + void DisplayToPlane(const Point2D& displayPoint, Point2D& planePointInMM) const; + + /** + * \brief Convert a 3D world index to the display point + * using the geometry of the renderWindow. + */ + void WorldToDisplay(const Point3D& worldIndex, Point2D& displayPoint) const; + + /** + * \brief Convert a 3D world index to the point on the viewport + * using the geometry of the renderWindow. + */ + void WorldToView(const Point3D& worldIndex, Point2D& viewPoint) const; + + /** + * \brief Convert a 2D plane coordinate to the display point + * using the geometry of the renderWindow. + */ + void PlaneToDisplay(const Point2D& planePointInMM, Point2D& displayPoint) const; + + /** + * \brief Convert a 2D plane coordinate to the point on the viewport + * using the geometry of the renderWindow. + */ + void PlaneToView(const Point2D& planePointInMM, Point2D& viewPoint) const; double GetScaleFactorMMPerDisplayUnit() const; Point2D GetDisplaySizeInMM() const; Point2D GetViewportSizeInMM() const; Point2D GetOriginInMM() const; itkGetConstMacro(ConstrainZoomingAndPanning, bool) virtual void SetConstrainZoomingAndPanning(bool constrain); protected: ~BaseRenderer() override; - //## @brief Call update of all mappers. To be implemented in subclasses. virtual void Update() = 0; - vtkRenderWindow *m_RenderWindow; - vtkRenderer *m_VtkRenderer; + vtkRenderWindow* m_RenderWindow; + vtkRenderer* m_VtkRenderer; - //## @brief MapperSlotId to use. Defines which kind of mapper (e.g., 2D or 3D) shoud be used. MapperSlotId m_MapperID; - - //## @brief The DataStorage that is used for rendering. DataStorage::Pointer m_DataStorage; - - //## @brief Timestamp of last call of Update(). unsigned long m_LastUpdateTime; - //## @brief CameraController for 3D rendering - //## @note preliminary. - itk::SmartPointer m_CameraController; + CameraController::Pointer m_CameraController; SliceNavigationController::Pointer m_SliceNavigationController; CameraRotationController::Pointer m_CameraRotationController; - //## @brief Sets m_CurrentWorldPlaneGeometry - virtual void SetCurrentWorldPlaneGeometry(const PlaneGeometry *geometry2d); - - //## @brief Sets m_CurrentWorldGeometry + void UpdateCurrentGeometries(); + virtual void SetCurrentWorldPlaneGeometry(const PlaneGeometry* geometry2d); virtual void SetCurrentWorldGeometry(const BaseGeometry *geometry); private: - //## m_WorldTimeGeometry is set by SetWorldGeometry if the passed BaseGeometry is a - //## TimeGeometry (or a sub-class of it). If it contains instances of SlicedGeometry3D, - //## m_Slice and m_TimeStep (set via SetSlice and SetTimeStep, respectively) define - //## which 2D geometry stored in m_WorldTimeGeometry (if available) - //## is used as m_CurrentWorldPlaneGeometry. - //## \sa m_CurrentWorldPlaneGeometry + /** + * \brief Pointer to the current TimeGeometry. + * + * This WorldTimeGeometry is used to extract a SlicedGeometry3D, + * using the current timestep (set via SetTimeStep). + * The time-extracted 3D-geometry is used as the "CurrentWorldgeometry". + * It will be set using the "SetCurrentWorldGeometry"-function. + * A PlaneGeometry can further be extracted using the current slice (set via SetSlice). + * The slice-extracted 2D-geometry is used as the "CurrentWorldPlaneGeometry". + * It will be set using the "SetCurrentWorldPlaneGeometry"-function. + */ TimeGeometry::ConstPointer m_WorldTimeGeometry; - //## Pointer to the current 3D-worldgeometry. + /** + * \brief Pointer to the current time-extracted 3D-geometry. + * + * This CurrentWorldGeometry is used to define the bounds for this + * BaseRenderer. + * It will be set using the "SetCurrentWorldGeometry"-function. + */ BaseGeometry::ConstPointer m_CurrentWorldGeometry; - //## Pointer to the current 2D-worldgeometry. The 2D-worldgeometry - //## describes the maximal area (2D manifold) to be rendered in case we - //## are doing 2D-rendering. - //## It is const, since we are not allowed to change it (it may be taken - //## directly from the geometry of an image-slice and thus it would be - //## very strange when suddenly the image-slice changes its geometry). + /** + * \brief Pointer to the current slice-extracted 2D-geometry. + * + * This CurrentWorldPlaneGeometry is used to define the maximal + * area (2D manifold) to be rendered in case we are doing 2D-rendering. + * It will be set using the "SetCurrentWorldPlaneGeometry"-function. + */ PlaneGeometry::Pointer m_CurrentWorldPlaneGeometry; - //## Defines together with m_TimeStep which 2D geometry stored in m_WorldTimeGeometry - //## is used as m_CurrentWorldPlaneGeometry: m_WorldTimeGeometry->GetPlaneGeometry(m_Slice, m_TimeStep). - //## \sa m_WorldTimeGeometry unsigned int m_Slice; - - //## Defines together with m_Slice which 2D geometry stored in m_WorldTimeGeometry - //## is used as m_CurrentWorldPlaneGeometry: m_WorldTimeGeometry->GetPlaneGeometry(m_Slice, m_TimeStep). - //## \sa m_WorldTimeGeometry unsigned int m_TimeStep; - //## @brief timestamp of last call of SetWorldGeometry itk::TimeStamp m_CurrentWorldPlaneGeometryUpdateTime; - - //## @brief timestamp of last change of the current time step itk::TimeStamp m_TimeStepUpdateTime; - //## @brief Helper class which establishes connection between Interactors and Dispatcher via a common DataStorage. - BindDispatcherInteractor *m_BindDispatcherInteractor; + BindDispatcherInteractor* m_BindDispatcherInteractor; - //## @brief Tells if the displayed region should be shifted or rescaled if the render window is resized. bool m_KeepDisplayedRegion; protected: - void PrintSelf(std::ostream &os, itk::Indent indent) const override; + void PrintSelf(std::ostream& os, itk::Indent indent) const override; - //## Data object containing the m_CurrentWorldPlaneGeometry defined above. PlaneGeometryData::Pointer m_CurrentWorldPlaneGeometryData; - - //## DataNode objects containing the m_CurrentWorldPlaneGeometryData defined above. DataNode::Pointer m_CurrentWorldPlaneGeometryNode; - - //## @brief test only unsigned long m_CurrentWorldPlaneGeometryTransformTime; std::string m_Name; double m_Bounds[6]; bool m_EmptyWorldGeometry; - typedef std::set LODEnabledMappersType; + typedef std::set LODEnabledMappersType; - /** Number of mappers which are visible and have level-of-detail - * rendering enabled */ unsigned int m_NumberOfVisibleLODEnabledMappers; - // Local Storage Handling for mappers - std::list m_RegisteredLocalStorageHandlers; + std::list m_RegisteredLocalStorageHandlers; bool m_ConstrainZoomingAndPanning; - }; } // namespace mitk #endif // MITKBASERENDERER_H diff --git a/Modules/Core/src/Interactions/mitkEventRecorder.cpp b/Modules/Core/src/Interactions/mitkEventRecorder.cpp index 11bdf36c00..429f00c5bd 100644 --- a/Modules/Core/src/Interactions/mitkEventRecorder.cpp +++ b/Modules/Core/src/Interactions/mitkEventRecorder.cpp @@ -1,188 +1,188 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkEventRecorder.h" #include "mitkEventFactory.h" #include "mitkInteractionEvent.h" #include "mitkInteractionEventConst.h" #include "vtkCamera.h" #include "mitkBaseRenderer.h" static void WriteEventXMLHeader(std::ofstream &stream) { stream << mitk::InteractionEventConst::xmlHead() << "\n"; } static void WriteEventXMLConfig(std::ofstream &stream) { // stream << " <" << mitk::InteractionEventConst::xmlTagConfigRoot() << ">\n"; // write renderer config // for all registered 2D renderers write name and viewdirection. auto rendererIterator = mitk::BaseRenderer::baseRendererMap.begin(); auto end = mitk::BaseRenderer::baseRendererMap.end(); for (; rendererIterator != end; ++rendererIterator) { std::string rendererName = (*rendererIterator).second->GetName(); mitk::SliceNavigationController::ViewDirection viewDirection = (*rendererIterator).second->GetSliceNavigationController()->GetDefaultViewDirection(); - mitk::BaseRenderer::MapperSlotId mapperID = (*rendererIterator).second->GetMapperID(); + MapperSlotId mapperID = (*rendererIterator).second->GetMapperID(); // stream << " <" << mitk::InteractionEventConst::xmlTagRenderer() << " " << mitk::InteractionEventConst::xmlEventPropertyRendererName() << "=\"" << rendererName << "\" " << mitk::InteractionEventConst::xmlEventPropertyViewDirection() << "=\"" << viewDirection << "\" " << mitk::InteractionEventConst::xmlEventPropertyMapperID() << "=\"" << mapperID << "\" " << mitk::InteractionEventConst::xmlRenderSizeX() << "=\"" << (*rendererIterator).second->GetSize()[0] << "\" " << mitk::InteractionEventConst::xmlRenderSizeY() << "=\"" << (*rendererIterator).second->GetSize()[1] << "\" " << mitk::InteractionEventConst::xmlRenderSizeZ() << "=\"" << (*rendererIterator).second->GetSize()[2] << "\" "; ; if ((*rendererIterator).second->GetMapperID() == mitk::BaseRenderer::Standard3D) { // For a 3D render window, rotation and zoom settings are determined by the vtkCamera parameters // these are recorded here: stream << mitk::InteractionEventConst::xmlViewUpX() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetViewUp()[0] << "\" " << mitk::InteractionEventConst::xmlViewUpY() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetViewUp()[1] << "\" " << mitk::InteractionEventConst::xmlViewUpZ() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetViewUp()[2] << "\" " << mitk::InteractionEventConst::xmlCameraFocalPointX() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetFocalPoint()[0] << "\" " << mitk::InteractionEventConst::xmlCameraFocalPointY() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetFocalPoint()[1] << "\" " << mitk::InteractionEventConst::xmlCameraFocalPointZ() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetFocalPoint()[2] << "\" " << mitk::InteractionEventConst::xmlCameraPositionX() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetPosition()[0] << "\" " << mitk::InteractionEventConst::xmlCameraPositionY() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetPosition()[1] << "\" " << mitk::InteractionEventConst::xmlCameraPositionZ() << "=\"" << (*rendererIterator).second->GetVtkRenderer()->GetActiveCamera()->GetPosition()[2] << "\" "; } stream << "/>\n"; } // stream << " \n"; } static void WriteEventXMLEventsOpen(std::ofstream &stream) { stream << " <" << mitk::InteractionEventConst::xmlTagEvents() << ">\n"; } static void WriteEventXMLEventsClose(std::ofstream &stream) { stream << " \n"; } static void WriteEventXMLInteractionsOpen(std::ofstream &stream) { stream << "<" << mitk::InteractionEventConst::xmlTagInteractions() << ">\n"; } static void WriteEventXMLInteractionsClose(std::ofstream &stream) { stream << ""; } static void WriteEventXMLClose(std::ofstream &stream) { WriteEventXMLEventsClose(stream); WriteEventXMLInteractionsClose(stream); } mitk::EventRecorder::EventRecorder() : m_Active(false) { } mitk::EventRecorder::~EventRecorder() { if (m_FileStream.is_open()) { m_FileStream.flush(); m_FileStream.close(); } } void mitk::EventRecorder::Notify(mitk::InteractionEvent *interactionEvent, bool /*isHandled*/) { if (m_FileStream.is_open()) m_FileStream << EventFactory::EventToXML(interactionEvent) << "\n"; } void mitk::EventRecorder::SetEventIgnoreList(std::vector list) { m_IgnoreList = list; } void mitk::EventRecorder::StartRecording() { if (m_FileName == "") { MITK_ERROR << "EventRecorder::StartRecording - Filename needs to be set first."; return; } if (m_FileStream.is_open()) { MITK_ERROR << "EventRecorder::StartRecording - Still recording. Stop recording before starting it again."; return; } m_FileStream.open(m_FileName.c_str(), std::ofstream::out); if (!m_FileStream.good()) { MITK_ERROR << "File " << m_FileName << " could not be opened!"; m_FileStream.close(); return; } m_Active = true; // write head and config // // // // // // ... // // WriteEventXMLHeader(m_FileStream); WriteEventXMLInteractionsOpen(m_FileStream); WriteEventXMLConfig(m_FileStream); WriteEventXMLEventsOpen(m_FileStream); } void mitk::EventRecorder::StopRecording() { if (m_FileStream.is_open()) { // write end tag // // WriteEventXMLClose(m_FileStream); m_FileStream.flush(); m_FileStream.close(); m_Active = false; } } diff --git a/Modules/Core/src/Rendering/mitkBaseRenderer.cpp b/Modules/Core/src/Rendering/mitkBaseRenderer.cpp index 9da8667558..08ccfa7762 100644 --- a/Modules/Core/src/Rendering/mitkBaseRenderer.cpp +++ b/Modules/Core/src/Rendering/mitkBaseRenderer.cpp @@ -1,783 +1,724 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkBaseRenderer.h" #include "mitkMapper.h" #include "mitkResliceMethodProperty.h" // Geometries -#include "mitkPlaneGeometry.h" #include "mitkSlicedGeometry3D.h" -// Controllers -#include "mitkCameraController.h" -#include "mitkCameraRotationController.h" -#include "mitkSliceNavigationController.h" - #include "mitkVtkLayerController.h" #include "mitkInteractionConst.h" #include "mitkProperties.h" #include "mitkWeakPointerProperty.h" // VTK #include #include -#include -#include #include #include #include namespace mitk { itkEventMacroDefinition(RendererResetEvent, itk::AnyEvent); } mitk::BaseRenderer::BaseRendererMapType mitk::BaseRenderer::baseRendererMap; mitk::BaseRenderer *mitk::BaseRenderer::GetInstance(vtkRenderWindow *renWin) { for (auto mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); ++mapit) { if ((*mapit).first == renWin) return (*mapit).second; } return nullptr; } void mitk::BaseRenderer::AddInstance(vtkRenderWindow *renWin, BaseRenderer *baseRenderer) { if (renWin == nullptr || baseRenderer == nullptr) return; // ensure that no BaseRenderer is managed twice mitk::BaseRenderer::RemoveInstance(renWin); baseRendererMap.insert(BaseRendererMapType::value_type(renWin, baseRenderer)); } void mitk::BaseRenderer::RemoveInstance(vtkRenderWindow *renWin) { auto mapit = baseRendererMap.find(renWin); if (mapit != baseRendererMap.end()) baseRendererMap.erase(mapit); } mitk::BaseRenderer *mitk::BaseRenderer::GetByName(const std::string &name) { for (auto mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); ++mapit) { if ((*mapit).second->m_Name == name) return (*mapit).second; } return nullptr; } vtkRenderWindow *mitk::BaseRenderer::GetRenderWindowByName(const std::string &name) { for (auto mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); ++mapit) { if ((*mapit).second->m_Name == name) return (*mapit).first; } return nullptr; } mitk::BaseRenderer::BaseRenderer(const char *name, vtkRenderWindow *renWin) : m_RenderWindow(nullptr), m_VtkRenderer(nullptr), - m_MapperID(defaultMapper), + m_MapperID(StandardMapperSlot::Standard2D), m_DataStorage(nullptr), m_LastUpdateTime(0), m_CameraController(nullptr), m_SliceNavigationController(nullptr), m_CameraRotationController(nullptr), m_WorldTimeGeometry(nullptr), m_CurrentWorldGeometry(nullptr), m_CurrentWorldPlaneGeometry(nullptr), m_Slice(0), m_TimeStep(), m_CurrentWorldPlaneGeometryUpdateTime(), m_TimeStepUpdateTime(), m_KeepDisplayedRegion(true), m_CurrentWorldPlaneGeometryData(nullptr), m_CurrentWorldPlaneGeometryNode(nullptr), m_CurrentWorldPlaneGeometryTransformTime(0), m_Name(name), m_EmptyWorldGeometry(true), m_NumberOfVisibleLODEnabledMappers(0) { m_Bounds[0] = 0; m_Bounds[1] = 0; m_Bounds[2] = 0; m_Bounds[3] = 0; m_Bounds[4] = 0; m_Bounds[5] = 0; if (name != nullptr) { m_Name = name; } else { m_Name = "unnamed renderer"; itkWarningMacro(<< "Created unnamed renderer. Bad for serialization. Please choose a name."); } if (renWin != nullptr) { m_RenderWindow = renWin; m_RenderWindow->Register(nullptr); } else { itkWarningMacro(<< "Created mitkBaseRenderer without vtkRenderWindow present."); } // instances.insert( this ); // adding this BaseRenderer to the List of all BaseRenderer m_BindDispatcherInteractor = new mitk::BindDispatcherInteractor(GetName()); WeakPointerProperty::Pointer rendererProp = WeakPointerProperty::New((itk::Object *)this); m_CurrentWorldPlaneGeometry = mitk::PlaneGeometry::New(); m_CurrentWorldPlaneGeometryData = mitk::PlaneGeometryData::New(); m_CurrentWorldPlaneGeometryData->SetPlaneGeometry(m_CurrentWorldPlaneGeometry); m_CurrentWorldPlaneGeometryNode = mitk::DataNode::New(); m_CurrentWorldPlaneGeometryNode->SetData(m_CurrentWorldPlaneGeometryData); m_CurrentWorldPlaneGeometryNode->GetPropertyList()->SetProperty("renderer", rendererProp); m_CurrentWorldPlaneGeometryNode->GetPropertyList()->SetProperty("layer", IntProperty::New(1000)); m_CurrentWorldPlaneGeometryNode->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New()); m_CurrentWorldPlaneGeometryNode->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(1)); m_CurrentWorldPlaneGeometryTransformTime = m_CurrentWorldPlaneGeometryNode->GetVtkTransform()->GetMTime(); mitk::SliceNavigationController::Pointer sliceNavigationController = mitk::SliceNavigationController::New(); sliceNavigationController->SetRenderer(this); sliceNavigationController->ConnectGeometrySendEvent(this); sliceNavigationController->ConnectGeometryUpdateEvent(this); sliceNavigationController->ConnectGeometrySliceEvent(this); sliceNavigationController->ConnectGeometryTimeEvent(this); m_SliceNavigationController = sliceNavigationController; m_CameraRotationController = mitk::CameraRotationController::New(); m_CameraRotationController->SetRenderWindow(m_RenderWindow); m_CameraRotationController->AcquireCamera(); m_CameraController = mitk::CameraController::New(); m_CameraController->SetRenderer(this); m_VtkRenderer = vtkRenderer::New(); m_VtkRenderer->SetMaximumNumberOfPeels(16); if (AntiAliasing::FastApproximate == RenderingManager::GetInstance()->GetAntiAliasing()) m_VtkRenderer->UseFXAAOn(); if (nullptr == mitk::VtkLayerController::GetInstance(m_RenderWindow)) mitk::VtkLayerController::AddInstance(m_RenderWindow, m_VtkRenderer); mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertSceneRenderer(m_VtkRenderer); } mitk::BaseRenderer::~BaseRenderer() { if (m_VtkRenderer != nullptr) { m_VtkRenderer->Delete(); m_VtkRenderer = nullptr; } if (m_CameraController.IsNotNull()) m_CameraController->SetRenderer(nullptr); mitk::VtkLayerController::RemoveInstance(m_RenderWindow); RemoveAllLocalStorages(); m_DataStorage = nullptr; if (m_BindDispatcherInteractor != nullptr) { delete m_BindDispatcherInteractor; } if (m_RenderWindow != nullptr) { m_RenderWindow->Delete(); m_RenderWindow = nullptr; } } -void mitk::BaseRenderer::SetMapperID(MapperSlotId id) -{ - if (m_MapperID != id) - { - bool useDepthPeeling = Standard3D == id; - m_VtkRenderer->SetUseDepthPeeling(useDepthPeeling); - m_VtkRenderer->SetUseDepthPeelingForVolumes(useDepthPeeling); - - m_MapperID = id; - this->Modified(); - } -} - void mitk::BaseRenderer::RemoveAllLocalStorages() { this->InvokeEvent(RendererResetEvent()); std::list::iterator it; for (it = m_RegisteredLocalStorageHandlers.begin(); it != m_RegisteredLocalStorageHandlers.end(); ++it) (*it)->ClearLocalStorage(this, false); m_RegisteredLocalStorageHandlers.clear(); } void mitk::BaseRenderer::RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh) { m_RegisteredLocalStorageHandlers.push_back(lsh); } -mitk::Dispatcher::Pointer mitk::BaseRenderer::GetDispatcher() const -{ - return m_BindDispatcherInteractor->GetDispatcher(); -} - void mitk::BaseRenderer::UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh) { m_RegisteredLocalStorageHandlers.remove(lsh); } void mitk::BaseRenderer::SetDataStorage(DataStorage *storage) { if (storage != m_DataStorage && storage != nullptr) { m_DataStorage = storage; m_BindDispatcherInteractor->SetDataStorage(m_DataStorage); this->Modified(); } } -const mitk::BaseRenderer::MapperSlotId mitk::BaseRenderer::defaultMapper = 1; - -void mitk::BaseRenderer::Paint() -{ -} - -void mitk::BaseRenderer::Initialize() +mitk::Dispatcher::Pointer mitk::BaseRenderer::GetDispatcher() const { + return m_BindDispatcherInteractor->GetDispatcher(); } void mitk::BaseRenderer::Resize(int w, int h) { - this->m_RenderWindow->SetSize(w, h); + m_RenderWindow->SetSize(w, h); } void mitk::BaseRenderer::InitRenderer(vtkRenderWindow *renderwindow) { if (m_RenderWindow != renderwindow) { if (m_RenderWindow != nullptr) { m_RenderWindow->Delete(); } m_RenderWindow = renderwindow; if (m_RenderWindow != nullptr) { m_RenderWindow->Register(nullptr); } } RemoveAllLocalStorages(); if (m_CameraController.IsNotNull()) { m_CameraController->SetRenderer(this); } } void mitk::BaseRenderer::InitSize(int w, int h) { - this->m_RenderWindow->SetSize(w, h); + m_RenderWindow->SetSize(w, h); +} + +void mitk::BaseRenderer::SetWorldTimeGeometry(const mitk::TimeGeometry* geometry) +{ + if (m_WorldTimeGeometry == geometry) + { + return; + } + + m_WorldTimeGeometry = geometry; + + this->UpdateCurrentGeometries(); } void mitk::BaseRenderer::SetSlice(unsigned int slice) { - if (m_Slice != slice) + if (m_Slice == slice) { - m_Slice = slice; - if (m_WorldTimeGeometry.IsNotNull()) - { - // get world geometry which may be rotated, for the current time step - SlicedGeometry3D *slicedWorldGeometry = - dynamic_cast(m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep).GetPointer()); - if (slicedWorldGeometry != nullptr) - { - // if slice position is part of the world geometry... - if (m_Slice >= slicedWorldGeometry->GetSlices()) - // set the current worldplanegeomety as the selected 2D slice of the world geometry - m_Slice = slicedWorldGeometry->GetSlices() - 1; - SetCurrentWorldPlaneGeometry(slicedWorldGeometry->GetPlaneGeometry(m_Slice)); - SetCurrentWorldGeometry(slicedWorldGeometry); - } - } - else - Modified(); + return; } + + m_Slice = slice; + + this->UpdateCurrentGeometries(); } void mitk::BaseRenderer::SetTimeStep(unsigned int timeStep) { - if (m_TimeStep != timeStep) + if (m_TimeStep == timeStep) { - m_TimeStep = timeStep; - m_TimeStepUpdateTime.Modified(); - - if (m_WorldTimeGeometry.IsNotNull()) - { - if (m_TimeStep >= m_WorldTimeGeometry->CountTimeSteps()) - m_TimeStep = m_WorldTimeGeometry->CountTimeSteps() - 1; - SlicedGeometry3D *slicedWorldGeometry = - dynamic_cast(m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep).GetPointer()); - if (slicedWorldGeometry != nullptr) - { - SetCurrentWorldPlaneGeometry(slicedWorldGeometry->GetPlaneGeometry(m_Slice)); - SetCurrentWorldGeometry(slicedWorldGeometry); - } - } - else - Modified(); + return; } + + m_TimeStep = timeStep; + m_TimeStepUpdateTime.Modified(); + + this->UpdateCurrentGeometries(); } -mitk::TimeStepType mitk::BaseRenderer::GetTimeStep(const mitk::BaseData *data) const +mitk::TimeStepType mitk::BaseRenderer::GetTimeStep(const mitk::BaseData* data) const { if ((data == nullptr) || (data->IsInitialized() == false)) { return -1; } return data->GetTimeGeometry()->TimePointToTimeStep(GetTime()); } mitk::ScalarType mitk::BaseRenderer::GetTime() const { if (m_WorldTimeGeometry.IsNull()) { return 0; } else { ScalarType timeInMS = m_WorldTimeGeometry->TimeStepToTimePoint(GetTimeStep()); if (timeInMS == itk::NumericTraits::NonpositiveMin()) return 0; else return timeInMS; } } -void mitk::BaseRenderer::SetWorldTimeGeometry(const mitk::TimeGeometry *geometry) +void mitk::BaseRenderer::SetGeometry(const itk::EventObject& geometrySendEvent) { - assert(geometry != nullptr); + const auto* sendEvent = dynamic_cast(&geometrySendEvent); - itkDebugMacro("setting WorldTimeGeometry to " << geometry); - if (m_WorldTimeGeometry != geometry) + if (nullptr == sendEvent) { - if (geometry->GetBoundingBoxInWorld()->GetDiagonalLength2() == 0) - return; - - m_WorldTimeGeometry = geometry; - itkDebugMacro("setting WorldTimeGeometry to " << m_WorldTimeGeometry); - - if (m_TimeStep >= m_WorldTimeGeometry->CountTimeSteps()) - m_TimeStep = m_WorldTimeGeometry->CountTimeSteps() - 1; - - BaseGeometry *geometry3d; - geometry3d = m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep); - SetWorldGeometry3D(geometry3d); + return; } + + SetWorldTimeGeometry(sendEvent->GetTimeGeometry()); } -void mitk::BaseRenderer::SetWorldGeometry3D(const mitk::BaseGeometry *geometry) +void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject& geometryUpdateEvent) { - itkDebugMacro("setting WorldGeometry3D to " << geometry); + const auto* updateEvent = dynamic_cast(&geometryUpdateEvent); - if (geometry->GetBoundingBox()->GetDiagonalLength2() == 0) + if (nullptr == updateEvent) + { return; - const SlicedGeometry3D *slicedWorldGeometry; - slicedWorldGeometry = dynamic_cast(geometry); + } - PlaneGeometry::ConstPointer geometry2d; - if (slicedWorldGeometry != nullptr) + if (m_CurrentWorldGeometry.IsNull()) { - if (m_Slice >= slicedWorldGeometry->GetSlices() && (m_Slice != 0)) - m_Slice = slicedWorldGeometry->GetSlices() - 1; - geometry2d = slicedWorldGeometry->GetPlaneGeometry(m_Slice); - if (geometry2d.IsNull()) - { - PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); - plane->InitializeStandardPlane(slicedWorldGeometry); - geometry2d = plane; - } - SetCurrentWorldGeometry(slicedWorldGeometry); + return; } - else + + const auto* slicedWorldGeometry = dynamic_cast(m_CurrentWorldGeometry.GetPointer()); + if (slicedWorldGeometry) { - geometry2d = dynamic_cast(geometry); - if (geometry2d.IsNull()) - { - PlaneGeometry::Pointer plane = PlaneGeometry::New(); - plane->InitializeStandardPlane(geometry); - geometry2d = plane; - } - SetCurrentWorldGeometry(geometry); - } - SetCurrentWorldPlaneGeometry(geometry2d); // calls Modified() + PlaneGeometry* geometry2D = slicedWorldGeometry->GetPlaneGeometry(m_Slice); - if (m_CurrentWorldPlaneGeometry.IsNull()) - itkWarningMacro("m_CurrentWorldPlaneGeometry is nullptr"); + SetCurrentWorldPlaneGeometry(geometry2D); // calls Modified() + } } -void mitk::BaseRenderer::SetCurrentWorldPlaneGeometry(const mitk::PlaneGeometry *geometry2d) +void mitk::BaseRenderer::SetGeometrySlice(const itk::EventObject& geometrySliceEvent) { - if (m_CurrentWorldPlaneGeometry != geometry2d) + const auto* sliceEvent = dynamic_cast(&geometrySliceEvent); + + if (nullptr == sliceEvent) { - m_CurrentWorldPlaneGeometry = geometry2d->Clone(); - m_CurrentWorldPlaneGeometryData->SetPlaneGeometry(m_CurrentWorldPlaneGeometry); - m_CurrentWorldPlaneGeometryUpdateTime.Modified(); - Modified(); + return; } -} - -void mitk::BaseRenderer::SendUpdateSlice() -{ - m_CurrentWorldPlaneGeometryUpdateTime.Modified(); -} -int *mitk::BaseRenderer::GetSize() const -{ - return this->m_RenderWindow->GetSize(); + this->SetSlice(sliceEvent->GetPos()); } -int *mitk::BaseRenderer::GetViewportSize() const +void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject& geometryTimeEvent) { - return this->m_VtkRenderer->GetSize(); -} + const auto* timeEvent = dynamic_cast(&geometryTimeEvent); -void mitk::BaseRenderer::SetCurrentWorldGeometry(const mitk::BaseGeometry *geometry) -{ - m_CurrentWorldGeometry = geometry; - if (geometry == nullptr) + if (nullptr == timeEvent) { - m_Bounds[0] = 0; - m_Bounds[1] = 0; - m_Bounds[2] = 0; - m_Bounds[3] = 0; - m_Bounds[4] = 0; - m_Bounds[5] = 0; - m_EmptyWorldGeometry = true; return; } - BoundingBox::Pointer boundingBox = m_CurrentWorldGeometry->CalculateBoundingBoxRelativeToTransform(nullptr); - const BoundingBox::BoundsArrayType &worldBounds = boundingBox->GetBounds(); - m_Bounds[0] = worldBounds[0]; - m_Bounds[1] = worldBounds[1]; - m_Bounds[2] = worldBounds[2]; - m_Bounds[3] = worldBounds[3]; - m_Bounds[4] = worldBounds[4]; - m_Bounds[5] = worldBounds[5]; - if (boundingBox->GetDiagonalLength2() <= mitk::eps) - m_EmptyWorldGeometry = true; - else - m_EmptyWorldGeometry = false; + + this->SetTimeStep(timeEvent->GetPos()); } -void mitk::BaseRenderer::SetGeometry(const itk::EventObject &geometrySendEvent) +void mitk::BaseRenderer::SendUpdateSlice() { - const auto *sendEvent = - dynamic_cast(&geometrySendEvent); - - assert(sendEvent != nullptr); - SetWorldTimeGeometry(sendEvent->GetTimeGeometry()); + m_CurrentWorldPlaneGeometryUpdateTime.Modified(); } -void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject &geometryUpdateEvent) +void mitk::BaseRenderer::SetMapperID(MapperSlotId id) { - const auto *updateEvent = - dynamic_cast(&geometryUpdateEvent); - - if (updateEvent == nullptr) - return; - - if (m_CurrentWorldGeometry.IsNotNull()) + if (m_MapperID != id) { - auto *slicedWorldGeometry = dynamic_cast(m_CurrentWorldGeometry.GetPointer()); - if (slicedWorldGeometry) - { - PlaneGeometry *geometry2D = slicedWorldGeometry->GetPlaneGeometry(m_Slice); + bool useDepthPeeling = Standard3D == id; + m_VtkRenderer->SetUseDepthPeeling(useDepthPeeling); + m_VtkRenderer->SetUseDepthPeelingForVolumes(useDepthPeeling); - SetCurrentWorldPlaneGeometry(geometry2D); // calls Modified() - } + m_MapperID = id; + this->Modified(); } } -void mitk::BaseRenderer::SetGeometrySlice(const itk::EventObject &geometrySliceEvent) +int* mitk::BaseRenderer::GetSize() const { - const auto *sliceEvent = - dynamic_cast(&geometrySliceEvent); - - assert(sliceEvent != nullptr); - SetSlice(sliceEvent->GetPos()); + return m_RenderWindow->GetSize(); } -void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject &geometryTimeEvent) +int* mitk::BaseRenderer::GetViewportSize() const { - const auto *timeEvent = - dynamic_cast(&geometryTimeEvent); - - assert(timeEvent != nullptr); - SetTimeStep(timeEvent->GetPos()); + return m_VtkRenderer->GetSize(); } -const double *mitk::BaseRenderer::GetBounds() const +const double* mitk::BaseRenderer::GetBounds() const { return m_Bounds; } -void mitk::BaseRenderer::DrawOverlayMouse(mitk::Point2D &itkNotUsed(p2d)) -{ - MITK_INFO << "BaseRenderer::DrawOverlayMouse()- should be inconcret implementation OpenGLRenderer." << std::endl; -} - void mitk::BaseRenderer::RequestUpdate() { SetConstrainZoomingAndPanning(true); - RenderingManager::GetInstance()->RequestUpdate(this->m_RenderWindow); + RenderingManager::GetInstance()->RequestUpdate(m_RenderWindow); } void mitk::BaseRenderer::ForceImmediateUpdate() { - RenderingManager::GetInstance()->ForceImmediateUpdate(this->m_RenderWindow); + RenderingManager::GetInstance()->ForceImmediateUpdate(m_RenderWindow); } unsigned int mitk::BaseRenderer::GetNumberOfVisibleLODEnabledMappers() const { return m_NumberOfVisibleLODEnabledMappers; } -/*! - Sets the new Navigation controller - */ void mitk::BaseRenderer::SetSliceNavigationController(mitk::SliceNavigationController *SlicenavigationController) { if (SlicenavigationController == nullptr) return; // copy worldgeometry SlicenavigationController->SetInputWorldTimeGeometry(SlicenavigationController->GetCreatedWorldGeometry()); SlicenavigationController->Update(); // set new m_SliceNavigationController = SlicenavigationController; m_SliceNavigationController->SetRenderer(this); if (m_SliceNavigationController.IsNotNull()) { m_SliceNavigationController->ConnectGeometrySendEvent(this); m_SliceNavigationController->ConnectGeometryUpdateEvent(this); m_SliceNavigationController->ConnectGeometrySliceEvent(this); m_SliceNavigationController->ConnectGeometryTimeEvent(this); } } -void mitk::BaseRenderer::DisplayToWorld(const Point2D &displayPoint, Point3D &worldIndex) const +void mitk::BaseRenderer::DisplayToWorld(const Point2D& displayPoint, Point3D& worldIndex) const { if (m_MapperID == BaseRenderer::Standard2D) { - double display[3], *world; + double display[3], * world; // For the rigth z-position in display coordinates, take the focal point, convert it to display and use it for // correct depth. - double *displayCoord; + double* displayCoord; double cameraFP[4]; // Get camera focal point and position. Convert to display (screen) // coordinates. We need a depth value for z-buffer. this->GetVtkRenderer()->GetActiveCamera()->GetFocalPoint(cameraFP); cameraFP[3] = 0.0; this->GetVtkRenderer()->SetWorldPoint(cameraFP[0], cameraFP[1], cameraFP[2], cameraFP[3]); this->GetVtkRenderer()->WorldToDisplay(); displayCoord = this->GetVtkRenderer()->GetDisplayPoint(); // now convert the display point to world coordinates display[0] = displayPoint[0]; display[1] = displayPoint[1]; display[2] = displayCoord[2]; this->GetVtkRenderer()->SetDisplayPoint(display); this->GetVtkRenderer()->DisplayToWorld(); world = this->GetVtkRenderer()->GetWorldPoint(); for (int i = 0; i < 3; i++) { worldIndex[i] = world[i] / world[3]; } } else if (m_MapperID == BaseRenderer::Standard3D) { - PickWorldPoint( - displayPoint, - worldIndex); // Seems to be the same code as above, but subclasses may contain different implementations. + // Seems to be the same code as above, but subclasses may contain different implementations. + PickWorldPoint(displayPoint, worldIndex); } - return; } void mitk::BaseRenderer::DisplayToPlane(const Point2D &displayPoint, Point2D &planePointInMM) const { if (m_MapperID == BaseRenderer::Standard2D) { Point3D worldPoint; this->DisplayToWorld(displayPoint, worldPoint); - this->m_CurrentWorldPlaneGeometry->Map(worldPoint, planePointInMM); + m_CurrentWorldPlaneGeometry->Map(worldPoint, planePointInMM); } else if (m_MapperID == BaseRenderer::Standard3D) { MITK_WARN << "No conversion possible with 3D mapper."; return; } return; } void mitk::BaseRenderer::WorldToDisplay(const Point3D &worldIndex, Point2D &displayPoint) const { double world[4], *display; world[0] = worldIndex[0]; world[1] = worldIndex[1]; world[2] = worldIndex[2]; world[3] = 1.0; this->GetVtkRenderer()->SetWorldPoint(world); this->GetVtkRenderer()->WorldToDisplay(); display = this->GetVtkRenderer()->GetDisplayPoint(); displayPoint[0] = display[0]; displayPoint[1] = display[1]; return; } void mitk::BaseRenderer::WorldToView(const mitk::Point3D &worldIndex, mitk::Point2D &viewPoint) const { double world[4], *view; world[0] = worldIndex[0]; world[1] = worldIndex[1]; world[2] = worldIndex[2]; world[3] = 1.0; this->GetVtkRenderer()->SetWorldPoint(world); this->GetVtkRenderer()->WorldToView(); view = this->GetVtkRenderer()->GetViewPoint(); this->GetVtkRenderer()->ViewToNormalizedViewport(view[0], view[1], view[2]); viewPoint[0] = view[0] * this->GetViewportSize()[0]; viewPoint[1] = view[1] * this->GetViewportSize()[1]; return; } void mitk::BaseRenderer::PlaneToDisplay(const Point2D &planePointInMM, Point2D &displayPoint) const { Point3D worldPoint; - this->m_CurrentWorldPlaneGeometry->Map(planePointInMM, worldPoint); + m_CurrentWorldPlaneGeometry->Map(planePointInMM, worldPoint); this->WorldToDisplay(worldPoint, displayPoint); return; } void mitk::BaseRenderer::PlaneToView(const Point2D &planePointInMM, Point2D &viewPoint) const { Point3D worldPoint; - this->m_CurrentWorldPlaneGeometry->Map(planePointInMM, worldPoint); + m_CurrentWorldPlaneGeometry->Map(planePointInMM, worldPoint); this->WorldToView(worldPoint,viewPoint); return; } double mitk::BaseRenderer::GetScaleFactorMMPerDisplayUnit() const { if (this->GetMapperID() == BaseRenderer::Standard2D) { // GetParallelScale returns half of the height of the render window in mm. // Divided by the half size of the Display size in pixel givest the mm per pixel. return this->GetVtkRenderer()->GetActiveCamera()->GetParallelScale() * 2.0 / GetViewportSize()[1]; } else return 1.0; } mitk::Point2D mitk::BaseRenderer::GetDisplaySizeInMM() const { Point2D dispSizeInMM; dispSizeInMM[0] = GetSizeX() * GetScaleFactorMMPerDisplayUnit(); dispSizeInMM[1] = GetSizeY() * GetScaleFactorMMPerDisplayUnit(); return dispSizeInMM; } mitk::Point2D mitk::BaseRenderer::GetViewportSizeInMM() const { Point2D dispSizeInMM; dispSizeInMM[0] = GetViewportSize()[0] * GetScaleFactorMMPerDisplayUnit(); dispSizeInMM[1] = GetViewportSize()[1] * GetScaleFactorMMPerDisplayUnit(); return dispSizeInMM; } mitk::Point2D mitk::BaseRenderer::GetOriginInMM() const { Point2D originPx; originPx[0] = m_VtkRenderer->GetOrigin()[0]; originPx[1] = m_VtkRenderer->GetOrigin()[1]; Point2D displayGeometryOriginInMM; DisplayToPlane(originPx, displayGeometryOriginInMM); // top left of the render window (Origin) return displayGeometryOriginInMM; } void mitk::BaseRenderer::SetConstrainZoomingAndPanning(bool constrain) { m_ConstrainZoomingAndPanning = constrain; if (m_ConstrainZoomingAndPanning) { this->GetCameraController()->AdjustCameraToPlane(); } } +void mitk::BaseRenderer::UpdateCurrentGeometries() +{ + if (m_WorldTimeGeometry.IsNull()) + { + // simply mark the base renderer as modified + Modified(); + } + + if (m_TimeStep >= m_WorldTimeGeometry->CountTimeSteps()) + { + m_TimeStep = m_WorldTimeGeometry->CountTimeSteps() - 1; + } + + auto slicedWorldGeometry = + dynamic_cast(m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep).GetPointer()); + if (slicedWorldGeometry != nullptr) + { + if (m_Slice >= slicedWorldGeometry->GetSlices()) + { + m_Slice = slicedWorldGeometry->GetSlices() - 1; + } + + SetCurrentWorldGeometry(slicedWorldGeometry); + SetCurrentWorldPlaneGeometry(slicedWorldGeometry->GetPlaneGeometry(m_Slice)); + } +} + +void mitk::BaseRenderer::SetCurrentWorldPlaneGeometry(const mitk::PlaneGeometry* geometry2d) +{ + if (m_CurrentWorldPlaneGeometry != geometry2d) + { + m_CurrentWorldPlaneGeometry = geometry2d->Clone(); + m_CurrentWorldPlaneGeometryData->SetPlaneGeometry(m_CurrentWorldPlaneGeometry); + m_CurrentWorldPlaneGeometryUpdateTime.Modified(); + Modified(); + } +} + +void mitk::BaseRenderer::SetCurrentWorldGeometry(const mitk::BaseGeometry* geometry) +{ + m_CurrentWorldGeometry = geometry; + if (geometry == nullptr) + { + m_Bounds[0] = 0; + m_Bounds[1] = 0; + m_Bounds[2] = 0; + m_Bounds[3] = 0; + m_Bounds[4] = 0; + m_Bounds[5] = 0; + m_EmptyWorldGeometry = true; + return; + } + BoundingBox::Pointer boundingBox = m_CurrentWorldGeometry->CalculateBoundingBoxRelativeToTransform(nullptr); + const BoundingBox::BoundsArrayType& worldBounds = boundingBox->GetBounds(); + m_Bounds[0] = worldBounds[0]; + m_Bounds[1] = worldBounds[1]; + m_Bounds[2] = worldBounds[2]; + m_Bounds[3] = worldBounds[3]; + m_Bounds[4] = worldBounds[4]; + m_Bounds[5] = worldBounds[5]; + if (boundingBox->GetDiagonalLength2() <= mitk::eps) + { + m_EmptyWorldGeometry = true; + } + else + { + m_EmptyWorldGeometry = false; + } +} + void mitk::BaseRenderer::PrintSelf(std::ostream &os, itk::Indent indent) const { os << indent << " MapperID: " << m_MapperID << std::endl; os << indent << " Slice: " << m_Slice << std::endl; os << indent << " TimeStep: " << m_TimeStep << std::endl; os << indent << " CurrentWorldPlaneGeometry: "; if (m_CurrentWorldPlaneGeometry.IsNull()) os << "nullptr" << std::endl; else m_CurrentWorldPlaneGeometry->Print(os, indent); os << indent << " CurrentWorldPlaneGeometryUpdateTime: " << m_CurrentWorldPlaneGeometryUpdateTime << std::endl; os << indent << " CurrentWorldPlaneGeometryTransformTime: " << m_CurrentWorldPlaneGeometryTransformTime << std::endl; Superclass::PrintSelf(os, indent); }