diff --git a/Modules/Core/include/mitkBaseRenderer.h b/Modules/Core/include/mitkBaseRenderer.h index a8dc4ef9be..d91f6a2b13 100644 --- a/Modules/Core/include/mitkBaseRenderer.h +++ b/Modules/Core/include/mitkBaseRenderer.h @@ -1,481 +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 * * 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; static BaseRendererMapType baseRendererMap; 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); mitkClassMacroItkParent(BaseRenderer, itk::Object); 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 Defines which view direction should be rendered. */ enum class ViewDirection { AXIAL = 0, SAGITTAL, CORONAL, THREE_D }; void RemoveAllLocalStorages(); void RegisterLocalStorageHandler(BaseLocalStorageHandler* lsh); void UnregisterLocalStorageHandler(BaseLocalStorageHandler* lsh); virtual void SetDataStorage(DataStorage* storage); virtual DataStorage::Pointer GetDataStorage() const { return m_DataStorage.GetPointer(); } vtkRenderWindow* GetRenderWindow() const { return m_RenderWindow; } vtkRenderer* GetVtkRenderer() const { return m_VtkRenderer; } /** * \brief Get the dispatcher, which handles events for this base renderer. */ Dispatcher::Pointer GetDispatcher() const; - /** - * \brief Do the rendering and flush the result. - */ - virtual void Paint(); - - /** - * \brief Initialize the RenderWindow. Should only be called from RenderWindow. - */ - virtual void Initialize(); - /** * \brief Set a new size for the render window. */ virtual void Resize(int w, int h); /** * \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 for the render window. */ virtual void InitSize(int w, int h); 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 time-extracted 3D-geometry. */ itkGetConstObjectMacro(CurrentWorldGeometry, BaseGeometry); /** * \brief Get the current slice-extracted 2D-geometry. */ itkGetConstObjectMacro(CurrentWorldPlaneGeometry, PlaneGeometry); virtual bool SetWorldGeometryToDataStorageBounds() { return false; } /** * \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 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 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 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 the update time of the current world plane geometry. */ itkGetMacro(CurrentWorldPlaneGeometryUpdateTime, unsigned long); /** * \brief Get timestamp of the update time of the current timestep. */ itkGetMacro(TimeStepUpdateTime, unsigned long); /** * \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 currently used mapperID. */ itkGetMacro(MapperID, MapperSlotId); itkGetConstMacro(MapperID, MapperSlotId); /** * \brief Set the used mapperID. */ virtual void SetMapperID(MapperSlotId id); virtual int* GetSize() const; virtual int* GetViewportSize() const; void SetSliceNavigationController(SliceNavigationController* SlicenavigationController); itkGetObjectMacro(CameraController, CameraController); itkGetObjectMacro(SliceNavigationController, SliceNavigationController); itkGetObjectMacro(CameraRotationController, CameraRotationController); itkGetMacro(EmptyWorldGeometry, bool); /** * \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 Return the name of the base renderer */ const char* GetName() const { return m_Name.c_str(); } /** * \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 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(); /** * \brief Return the number of mappers which are visible and have * level-of-detail rendering enabled. */ unsigned int GetNumberOfVisibleLODEnabledMappers() 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; virtual void Update() = 0; vtkRenderWindow* m_RenderWindow; vtkRenderer* m_VtkRenderer; MapperSlotId m_MapperID; DataStorage::Pointer m_DataStorage; unsigned long m_LastUpdateTime; - itk::SmartPointer m_CameraController; + CameraController::Pointer m_CameraController; SliceNavigationController::Pointer m_SliceNavigationController; CameraRotationController::Pointer m_CameraRotationController; void UpdateCurrentGeometries(); virtual void SetCurrentWorldPlaneGeometry(const PlaneGeometry* geometry2d); virtual void SetCurrentWorldGeometry(const BaseGeometry *geometry); private: /** * \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; /** * \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; /** * \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; unsigned int m_Slice; unsigned int m_TimeStep; itk::TimeStamp m_CurrentWorldPlaneGeometryUpdateTime; itk::TimeStamp m_TimeStepUpdateTime; BindDispatcherInteractor* m_BindDispatcherInteractor; bool m_KeepDisplayedRegion; protected: void PrintSelf(std::ostream& os, itk::Indent indent) const override; PlaneGeometryData::Pointer m_CurrentWorldPlaneGeometryData; DataNode::Pointer m_CurrentWorldPlaneGeometryNode; unsigned long m_CurrentWorldPlaneGeometryTransformTime; std::string m_Name; double m_Bounds[6]; bool m_EmptyWorldGeometry; typedef std::set LODEnabledMappersType; unsigned int m_NumberOfVisibleLODEnabledMappers; std::list m_RegisteredLocalStorageHandlers; bool m_ConstrainZoomingAndPanning; }; } // namespace mitk #endif // MITKBASERENDERER_H diff --git a/Modules/Core/src/Rendering/mitkBaseRenderer.cpp b/Modules/Core/src/Rendering/mitkBaseRenderer.cpp index 5ee5980071..08ccfa7762 100644 --- a/Modules/Core/src/Rendering/mitkBaseRenderer.cpp +++ b/Modules/Core/src/Rendering/mitkBaseRenderer.cpp @@ -1,745 +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::SetSlice(unsigned int slice) +void mitk::BaseRenderer::SetWorldTimeGeometry(const mitk::TimeGeometry* geometry) { - if (m_Slice == slice) + if (m_WorldTimeGeometry == geometry) { return; } - m_Slice = slice; + m_WorldTimeGeometry = geometry; this->UpdateCurrentGeometries(); } -void mitk::BaseRenderer::SetTimeStep(unsigned int timeStep) +void mitk::BaseRenderer::SetSlice(unsigned int slice) { - if (m_TimeStep == timeStep) + if (m_Slice == slice) { return; } - m_TimeStep = timeStep; - m_TimeStepUpdateTime.Modified(); + m_Slice = slice; this->UpdateCurrentGeometries(); } -void mitk::BaseRenderer::UpdateCurrentGeometries() +void mitk::BaseRenderer::SetTimeStep(unsigned int timeStep) { - if (m_WorldTimeGeometry.IsNull()) - { - // simply mark the base renderer as modified - Modified(); - } - - if (m_TimeStep >= m_WorldTimeGeometry->CountTimeSteps()) + if (m_TimeStep == timeStep) { - m_TimeStep = m_WorldTimeGeometry->CountTimeSteps() - 1; + return; } - auto slicedWorldGeometry = - dynamic_cast(m_WorldTimeGeometry->GetGeometryForTimeStep(m_TimeStep).GetPointer()); - if (slicedWorldGeometry != nullptr) - { - if (m_Slice >= slicedWorldGeometry->GetSlices()) - { - m_Slice = slicedWorldGeometry->GetSlices() - 1; - } + m_TimeStep = timeStep; + m_TimeStepUpdateTime.Modified(); - SetCurrentWorldPlaneGeometry(slicedWorldGeometry->GetPlaneGeometry(m_Slice)); - SetCurrentWorldGeometry(slicedWorldGeometry); - } + 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) -{ - if (m_WorldTimeGeometry == geometry) - { - return; - } - - m_WorldTimeGeometry = geometry; - - this->UpdateCurrentGeometries(); -} - -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::SendUpdateSlice() -{ - m_CurrentWorldPlaneGeometryUpdateTime.Modified(); -} - -int *mitk::BaseRenderer::GetSize() const -{ - return this->m_RenderWindow->GetSize(); -} - -int *mitk::BaseRenderer::GetViewportSize() const -{ - return this->m_VtkRenderer->GetSize(); -} - -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::SetGeometry(const itk::EventObject &geometrySendEvent) +void mitk::BaseRenderer::SetGeometry(const itk::EventObject& geometrySendEvent) { const auto* sendEvent = dynamic_cast(&geometrySendEvent); if (nullptr == sendEvent) { return; } SetWorldTimeGeometry(sendEvent->GetTimeGeometry()); } -void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject &geometryUpdateEvent) +void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject& geometryUpdateEvent) { const auto* updateEvent = dynamic_cast(&geometryUpdateEvent); if (nullptr == updateEvent) { return; } if (m_CurrentWorldGeometry.IsNull()) { return; } - const auto* slicedWorldGeometry = dynamic_cast(m_CurrentWorldGeometry.GetPointer()); + const auto* slicedWorldGeometry = dynamic_cast(m_CurrentWorldGeometry.GetPointer()); if (slicedWorldGeometry) { - PlaneGeometry *geometry2D = slicedWorldGeometry->GetPlaneGeometry(m_Slice); + PlaneGeometry* geometry2D = slicedWorldGeometry->GetPlaneGeometry(m_Slice); SetCurrentWorldPlaneGeometry(geometry2D); // calls Modified() } } -void mitk::BaseRenderer::SetGeometrySlice(const itk::EventObject &geometrySliceEvent) +void mitk::BaseRenderer::SetGeometrySlice(const itk::EventObject& geometrySliceEvent) { const auto* sliceEvent = dynamic_cast(&geometrySliceEvent); if (nullptr == sliceEvent) { return; } this->SetSlice(sliceEvent->GetPos()); } -void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject &geometryTimeEvent) +void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject& geometryTimeEvent) { const auto* timeEvent = dynamic_cast(&geometryTimeEvent); if (nullptr == timeEvent) { return; } this->SetTimeStep(timeEvent->GetPos()); } -const double *mitk::BaseRenderer::GetBounds() const +void mitk::BaseRenderer::SendUpdateSlice() { - return m_Bounds; + m_CurrentWorldPlaneGeometryUpdateTime.Modified(); } -void mitk::BaseRenderer::DrawOverlayMouse(mitk::Point2D &itkNotUsed(p2d)) +void mitk::BaseRenderer::SetMapperID(MapperSlotId id) { - MITK_INFO << "BaseRenderer::DrawOverlayMouse()- should be inconcret implementation OpenGLRenderer." << std::endl; + if (m_MapperID != id) + { + bool useDepthPeeling = Standard3D == id; + m_VtkRenderer->SetUseDepthPeeling(useDepthPeeling); + m_VtkRenderer->SetUseDepthPeelingForVolumes(useDepthPeeling); + + m_MapperID = id; + this->Modified(); + } +} + +int* mitk::BaseRenderer::GetSize() const +{ + return m_RenderWindow->GetSize(); +} + +int* mitk::BaseRenderer::GetViewportSize() const +{ + return m_VtkRenderer->GetSize(); +} + +const double* mitk::BaseRenderer::GetBounds() const +{ + return m_Bounds; } 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; } 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); }