diff --git a/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h b/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h index a7e3f2db28..ee679cf6a2 100644 --- a/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h +++ b/Modules/Core/TestingHelper/include/mitkRenderingTestHelper.h @@ -1,225 +1,225 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkRenderingTestHelper_h #define mitkRenderingTestHelper_h #include #include #include #include #include class vtkRenderWindow; class vtkRenderer; namespace mitk { class MITKTESTINGHELPER_EXPORT RenderingTestHelper { public: /** @brief Generate a rendering test helper object including a render window of the size width * height (in pixel). @param argc Number of parameters. (here: Images) "Usage: [filename1 filenam2 -V referenceScreenshot (optional -T /directory/to/save/differenceImage)] @param argv Given parameters. If no data is inserted via commandline, you can add data later via AddNodeToDataStorage(). @param renderingMode The rendering mode. **/ RenderingTestHelper( int width, int height, int argc, char *argv[], - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::NoAntiAliasing); + BaseRenderer::RenderingMode renderingMode = BaseRenderer::RenderingMode::NoAntiAliasing); /** @brief Generate a rendering test helper object including a render window of the size width * height (in * pixel).*/ RenderingTestHelper( int width, int height, - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::NoAntiAliasing); + BaseRenderer::RenderingMode renderingMode = BaseRenderer::RenderingMode::NoAntiAliasing); /** Default destructor */ ~RenderingTestHelper(); /** @brief Getter for the vtkRenderer. **/ vtkRenderer *GetVtkRenderer(); /** @brief Getter for the vtkRenderWindow which should be used to call vtkRegressionTestImage. **/ vtkRenderWindow *GetVtkRenderWindow(); /** @brief Method can be used to save a screenshot (e.g. reference screenshot as a .png file. @param fileName The filename of the new screenshot (including path). **/ void SaveAsPNG(std::string fileName); /** * @brief SetStopRenderWindow Convenience method to make the renderwindow hold after rendering. Usefull for * debugging. * @param flag Flag indicating whether the renderwindow should automatically close (false, default) or stay open * (true). Usefull for debugging. */ void SetAutomaticallyCloseRenderWindow(bool automaticallyCloseRenderWindow); /** @brief This method set the property of the member datastorage @param property Set a property for each image in the datastorage m_DataStorage. If you want to set the property for a single data node, use GetDataStorage() and set the property yourself for the destinct node. **/ void SetImageProperty(const char *propertyKey, mitk::BaseProperty *property); /** @brief Set the view direction of the renderwindow (e.g. sagittal, coronal, axial) **/ void SetViewDirection(mitk::SliceNavigationController::ViewDirection viewDirection); /** @brief Reorient the slice (e.g. rotation and translation like the swivel mode). **/ void ReorientSlices(mitk::Point3D origin, mitk::Vector3D rotation); /** @brief Render everything into an mitkRenderWindow. Call SetViewDirection() and SetProperty() before this method. **/ void Render(); /** @brief Returns the datastorage, in order to modify the data inside a rendering test. **/ mitk::DataStorage::Pointer GetDataStorage(); /** * @brief SetMapperID Change between Standard2D and 3D mappers. * @param id Enum mitk::BaseRenderer::StandardMapperSlot which defines the mapper. */ void SetMapperID(mitk::BaseRenderer::StandardMapperSlot id); /** * @brief AddNodeToStorage Add a node to the datastorage and perform a reinit which is necessary for rendering. * @param node The data you want to add. */ void AddNodeToStorage(mitk::DataNode::Pointer node); /** * @brief SetMapperIDToRender3D Convenience method to render in a 3D renderwindow. * @warning Does not add helper objects like the image planes to render images in 3D. */ void SetMapperIDToRender3D(); /** * @brief SetMapperIDToRender2D Convenience method to render in a 2D renderwindow. */ void SetMapperIDToRender2D(); /** * @brief SaveReferenceScreenShot Convenience method to save a reference screen shot. * @param fileName Path/to/save/the/png/file. */ void SaveReferenceScreenShot(std::string fileName); /** * @brief CompareRenderWindowAgainstReference Convenience method to compare the image rendered in the internal renderwindow against a reference screen shot. * Usage of vtkTesting::Test: vtkTesting::Test( argc, argv, vtkRenderWindow, threshold ) Set a vtkRenderWindow containing the desired scene. This is automatically rendered. vtkTesting::Test() automatically searches in argc and argv[] for a path a valid image with -V. If the test failed with the first image (foo.png) it checks if there are images of the form foo_N.png (where N=1,2,3...) and compare against them. This allows for multiple valid images. * @param argc Number of arguments. * @param argv Arguments must(!) contain the term "-V Path/To/Valid/Image.png" * @param threshold Allowed difference between two images. Default = 10.0 and was taken from VTK. * @return True if the images are equal regarding the threshold. False in all other cases. */ bool CompareRenderWindowAgainstReference(int argc, char *argv[], double threshold = 10.0); /** @brief Returns true if the opengl context is compatible for advanced vtk effects **/ bool IsAdvancedOpenGL(); /** * @brief The ArgcHelperClass class is a convinience class to convert a vector * of strings to the standard c++ argv and argc arguments. This is necessary for * the vtkTesting::Test, since is requires the reference image (and other * optional parameters) via command line. */ class ArgcHelperClass { private: /** * Members for conversion. */ std::vector argv; std::vector> argvec; public: ArgcHelperClass(const std::vector &argstrings) : argv(argstrings.size() + 1), argvec(argstrings.size() + 1) { std::vector cmdArgs; cmdArgs.push_back(mitk::IOUtil::GetProgramPath()); cmdArgs.insert(cmdArgs.end(), argstrings.begin(), argstrings.end()); for (std::size_t i = 0; i < cmdArgs.size(); ++i) { argvec[i].assign(cmdArgs[i].begin(), cmdArgs[i].end()); argvec[i].push_back('\0'); argv[i] = &argvec[i][0]; } } char **GetArgv() { return &argv[0]; } int GetArgc() { return argv.size(); } }; protected: /** * @brief Initialize Internal method to initialize the renderwindow and set the datastorage. * @param width Height of renderwindow. * @param height Width of renderwindow. * @param renderingMode The rendering mode. */ void Initialize( int width, int height, - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::NoAntiAliasing); + BaseRenderer::RenderingMode renderingMode = BaseRenderer::RenderingMode::NoAntiAliasing); /** @brief Prints the opengl information, e.g. version, vendor and extensions, * This function can only be called after an opengl context is active. * It only prints the context after the vtkRenderwindow is fully initialized. **/ void PrintGLInfo(); /** @brief This method tries to load the given file into a member datastorage, in order to render it. @param fileName The filename of the file to be loaded (including path). **/ void AddToStorage(const std::string &filename); /** @brief This method tries to parse the given argv for files (e.g. images) and load them into a member datastorage, in order to render it. @param argc Number of parameters. @param argv Given parameters. **/ void SetInputFileNames(int argc, char *argv[]); mitk::RenderWindow::Pointer m_RenderWindow; //<< Contains the mitkRenderWindow into which the test renders the data mitk::DataStorage::Pointer m_DataStorage; //<< Contains the mitkDataStorage which contains the data to be rendered bool m_AutomaticallyCloseRenderWindow; //<< Flag indicating whether the renderwindow should automatically close (true, // default) or stay open (false). Usefull for debugging. }; } // namespace mitk #endif diff --git a/Modules/Core/TestingHelper/src/mitkRenderingTestHelper.cpp b/Modules/Core/TestingHelper/src/mitkRenderingTestHelper.cpp index 0b75af32f4..9a66290a77 100644 --- a/Modules/Core/TestingHelper/src/mitkRenderingTestHelper.cpp +++ b/Modules/Core/TestingHelper/src/mitkRenderingTestHelper.cpp @@ -1,315 +1,315 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // VTK #include #include #include #include #include // MITK #include #include #include #include #include #include #include #include // include gl to read out properties #include #include #if defined _MSC_VER #if _MSC_VER >= 1700 #define RESIZE_WORKAROUND #endif #endif #ifdef RESIZE_WORKAROUND #include "vtkWin32OpenGLRenderWindow.h" #endif // VTK Testing to compare the rendered image pixel-wise against a reference screen shot #include "vtkTesting.h" mitk::RenderingTestHelper::RenderingTestHelper(int width, int height, - mitk::BaseRenderer::RenderingMode::Type renderingMode) + BaseRenderer::RenderingMode renderingMode) : m_AutomaticallyCloseRenderWindow(true) { this->Initialize(width, height, renderingMode); } mitk::RenderingTestHelper::RenderingTestHelper( - int width, int height, int argc, char *argv[], mitk::BaseRenderer::RenderingMode::Type renderingMode) + int width, int height, int argc, char *argv[], BaseRenderer::RenderingMode renderingMode) : m_AutomaticallyCloseRenderWindow(true) { this->Initialize(width, height, renderingMode); this->SetInputFileNames(argc, argv); } -void mitk::RenderingTestHelper::Initialize(int width, int height, mitk::BaseRenderer::RenderingMode::Type renderingMode) +void mitk::RenderingTestHelper::Initialize(int width, int height, BaseRenderer::RenderingMode renderingMode) { mitk::UIDGenerator uidGen = mitk::UIDGenerator("UnnamedRenderer_", 8); m_RenderWindow = mitk::RenderWindow::New(nullptr, uidGen.GetUID().c_str(), nullptr, renderingMode); m_DataStorage = mitk::StandaloneDataStorage::New(); m_RenderWindow->GetRenderer()->SetDataStorage(m_DataStorage); this->SetMapperIDToRender2D(); this->GetVtkRenderWindow()->SetSize(width, height); if (!IsAdvancedOpenGL()) { mitkThrowException(mitk::TestNotRunException) << "Insufficient OpenGL version"; } #ifdef RESIZE_WORKAROUND HWND hWnd = static_cast(this->GetVtkRenderWindow())->GetWindowId(); RECT r; r.left = 10; r.top = 10; r.right = r.left + width; r.bottom = r.top + height; LONG style = GetWindowLong(hWnd, GWL_STYLE); AdjustWindowRect(&r, style, FALSE); MITK_INFO << "WANTED:"; MITK_INFO << r.right - r.left; MITK_INFO << r.bottom - r.top; RECT rect; if (GetWindowRect(hWnd, &rect)) { int width = rect.right - rect.left; int height = rect.bottom - rect.top; MITK_INFO << "ACTUAL:"; MITK_INFO << width; MITK_INFO << height; } SetWindowPos(hWnd, HWND_TOP, 0, 0, r.right - r.left, r.bottom - r.top, SWP_NOZORDER); GetWindowRect(hWnd, &rect); int width2 = rect.right - rect.left; int height2 = rect.bottom - rect.top; MITK_INFO << "ACTUAL2:"; MITK_INFO << width2; MITK_INFO << height2; SetWindowPos(hWnd, HWND_TOP, 0, 0, 2 * (r.right - r.left) - width2, 2 * (r.bottom - r.top) - height2, SWP_NOZORDER); #endif m_RenderWindow->GetRenderer()->Resize(width, height); // Prints the glinfo after creation of the vtkrenderwindow, we always want to do this for debugging. this->PrintGLInfo(); } mitk::RenderingTestHelper::~RenderingTestHelper() { } bool mitk::RenderingTestHelper::IsAdvancedOpenGL() { const GLubyte *version = glGetString(GL_VERSION); if (!version) return false; return *version >= '2'; } void mitk::RenderingTestHelper::PrintGLInfo() { GLint maxTextureSize; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); ; //MITK_INFO << "OpenGL Render Context Information: \n" // << "- GL_VENDOR: " << glGetString(GL_VENDOR) << "\n" // << "- GL_RENDERER: " << glGetString(GL_RENDERER) << "\n" // << "- GL_VERSION: " << glGetString(GL_VERSION) << "\n" // << "- GL_MAX_TEXTURE_SIZE: " << maxTextureSize << "\n" // << "- GL_EXTENSIONS: " << glGetString(GL_EXTENSIONS); } void mitk::RenderingTestHelper::SetMapperID(mitk::BaseRenderer::StandardMapperSlot id) { m_RenderWindow->GetRenderer()->SetMapperID(id); } void mitk::RenderingTestHelper::SetMapperIDToRender3D() { this->SetMapperID(mitk::BaseRenderer::Standard3D); mitk::RenderingManager::GetInstance()->InitializeViews( this->GetDataStorage()->ComputeBoundingGeometry3D(this->GetDataStorage()->GetAll())); } void mitk::RenderingTestHelper::SetMapperIDToRender2D() { this->SetMapperID(mitk::BaseRenderer::Standard2D); } void mitk::RenderingTestHelper::Render() { // if the datastorage is initialized and at least 1 image is loaded render it if (m_DataStorage.IsNotNull() || m_DataStorage->GetAll()->Size() >= 1) { // Prepare the VTK camera before rendering. m_RenderWindow->GetRenderer()->PrepareRender(); this->GetVtkRenderWindow()->Render(); this->GetVtkRenderWindow()->WaitForCompletion(); if (m_AutomaticallyCloseRenderWindow == false) { // Use interaction to stop the test this->GetVtkRenderWindow()->GetInteractor()->Start(); } } else { MITK_ERROR << "No images loaded in data storage!"; } } mitk::DataStorage::Pointer mitk::RenderingTestHelper::GetDataStorage() { return m_DataStorage; } void mitk::RenderingTestHelper::SetInputFileNames(int argc, char *argv[]) { // i is set 1, because 0 is the testname as string // parse parameters for (int i = 1; i < argc; ++i) { // add everything to a list but -T and -V std::string tmp = argv[i]; if ((tmp.compare("-T")) && (tmp.compare("-V"))) { this->AddToStorage(tmp); } else { break; } } } void mitk::RenderingTestHelper::SetViewDirection(mitk::SliceNavigationController::ViewDirection viewDirection) { mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow()) ->GetSliceNavigationController() ->SetDefaultViewDirection(viewDirection); mitk::RenderingManager::GetInstance()->InitializeViews( m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll())); } void mitk::RenderingTestHelper::ReorientSlices(mitk::Point3D origin, mitk::Vector3D rotation) { mitk::SliceNavigationController::Pointer sliceNavigationController = mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetSliceNavigationController(); sliceNavigationController->ReorientSlices(origin, rotation); } vtkRenderer *mitk::RenderingTestHelper::GetVtkRenderer() { return m_RenderWindow->GetRenderer()->GetVtkRenderer(); } void mitk::RenderingTestHelper::SetImageProperty(const char *propertyKey, mitk::BaseProperty *property) { this->m_DataStorage->GetNode(mitk::NodePredicateDataType::New("Image"))->SetProperty(propertyKey, property); } vtkRenderWindow *mitk::RenderingTestHelper::GetVtkRenderWindow() { return m_RenderWindow->GetVtkRenderWindow(); } bool mitk::RenderingTestHelper::CompareRenderWindowAgainstReference(int argc, char *argv[], double threshold) { this->Render(); // retVal meanings: (see VTK/Rendering/vtkTesting.h) // 0 = test failed // 1 = test passed // 2 = test not run // 3 = something with vtkInteraction if (vtkTesting::Test(argc, argv, this->GetVtkRenderWindow(), threshold) == 1) return true; else return false; } // method to save a screenshot of the renderwindow (e.g. create a reference screenshot) void mitk::RenderingTestHelper::SaveAsPNG(std::string fileName) { vtkSmartPointer renderer = this->GetVtkRenderer(); bool doubleBuffering(renderer->GetRenderWindow()->GetDoubleBuffer()); renderer->GetRenderWindow()->DoubleBufferOff(); vtkSmartPointer magnifier = vtkSmartPointer::New(); magnifier->SetInput(renderer); magnifier->SetMagnification(1); vtkSmartPointer fileWriter = vtkSmartPointer::New(); fileWriter->SetInputConnection(magnifier->GetOutputPort()); fileWriter->SetFileName(fileName.c_str()); fileWriter->Write(); renderer->GetRenderWindow()->SetDoubleBuffer(doubleBuffering); } void mitk::RenderingTestHelper::SetAutomaticallyCloseRenderWindow(bool automaticallyCloseRenderWindow) { m_AutomaticallyCloseRenderWindow = automaticallyCloseRenderWindow; } void mitk::RenderingTestHelper::SaveReferenceScreenShot(std::string fileName) { this->SaveAsPNG(fileName); } void mitk::RenderingTestHelper::AddToStorage(const std::string &filename) { try { mitk::IOUtil::Load(filename, *m_DataStorage.GetPointer()); mitk::RenderingManager::GetInstance()->InitializeViews( m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll())); } catch ( const itk::ExceptionObject &e ) { MITK_ERROR << "Failed loading test data '" << filename << "': " << e.what(); } } void mitk::RenderingTestHelper::AddNodeToStorage(mitk::DataNode::Pointer node) { this->m_DataStorage->Add(node); mitk::RenderingManager::GetInstance()->InitializeViews( m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll())); } diff --git a/Modules/Core/include/mitkBaseRenderer.h b/Modules/Core/include/mitkBaseRenderer.h index d122e3c3fd..591da19453 100644 --- a/Modules/Core/include/mitkBaseRenderer.h +++ b/Modules/Core/include/mitkBaseRenderer.h @@ -1,568 +1,565 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 #define BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 #include "mitkCameraRotationController.h" #include "mitkDataStorage.h" #include "mitkPlaneGeometry.h" #include "mitkPlaneGeometryData.h" #include "mitkSliceNavigationController.h" #include "mitkTimeGeometry.h" #include "mitkBindDispatcherInteractor.h" #include "mitkDispatcher.h" #include #include #include #include // DEPRECATED #include namespace mitk { class NavigationController; class SliceNavigationController; class CameraRotationController; class CameraController; class DataStorage; class Mapper; class BaseLocalStorageHandler; class KeyEvent; //##Documentation //## @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 class MITKCORE_EXPORT BaseRenderer : public itk::Object { public: /** \brief This rendering mode enumeration is specified at various constructors * of the Renderer and RenderWindow classes, which autoconfigures the * respective VTK objects. This has to be done at construction time because later * configuring turns out to be not working on most platforms. */ - struct RenderingMode + enum class RenderingMode : int { - enum Type - { - NoAntiAliasing = 0, - FastApproximateAntiAliasing = 1 // In contrast to MSAA, FXAA works with depth peeling as it is - // applied as a post-processing pass. - }; + NoAntiAliasing = 0, + FastApproximateAntiAliasing = 1 // In contrast to MSAA, FXAA works with depth peeling as it is + // applied in a post-processing pass. }; 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 *GetByName(const std::string &name); static vtkRenderWindow *GetRenderWindowByName(const std::string &name); #pragma GCC visibility push(default) itkEventMacro(RendererResetEvent, itk::AnyEvent); #pragma GCC visibility pop /** Standard class typedefs. */ mitkClassMacroItkParent(BaseRenderer, itk::Object); BaseRenderer(const char *name = nullptr, vtkRenderWindow *renWin = nullptr, mitk::RenderingManager *rm = nullptr, - RenderingMode::Type mode = RenderingMode::FastApproximateAntiAliasing); + RenderingMode mode = RenderingMode::FastApproximateAntiAliasing); //##Documentation //## @brief MapperSlotId defines which kind of mapper (e.g. 2D or 3D) should be used. typedef int MapperSlotId; enum StandardMapperSlot { Standard2D = 1, Standard3D = 2 }; //##Documentation //## @brief Possible view directions for render windows. enum class ViewDirection { AXIAL = 0, SAGITTAL, CORONAL, THREE_D }; virtual void SetDataStorage(DataStorage *storage); ///< set the datastorage that will be used for rendering //##Documentation //## return the DataStorage that is used for rendering virtual DataStorage::Pointer GetDataStorage() const { return m_DataStorage.GetPointer(); } //##Documentation //## @brief Access the RenderWindow into which this renderer renders. vtkRenderWindow *GetRenderWindow() const { return m_RenderWindow; } vtkRenderer *GetVtkRenderer() const { return m_VtkRenderer; } //##Documentation //## @brief Returns the Dispatcher which handles Events for this BaseRenderer Dispatcher::Pointer GetDispatcher() const; //##Documentation //## @brief Default mapper id to use. static const MapperSlotId defaultMapper; //##Documentation //## @brief Do the rendering and flush the result. virtual void Paint(); //##Documentation //## @brief Initialize the RenderWindow. Should only be called from RenderWindow. virtual void Initialize(); //##Documentation //## @brief Called to inform the renderer that the RenderWindow has been resized. virtual void Resize(int w, int h); //##Documentation //## @brief Initialize the renderer with a RenderWindow (@a renderwindow). virtual void InitRenderer(vtkRenderWindow *renderwindow); //##Documentation //## @brief Set the initial size. Called by RenderWindow after it has become //## visible for the first time. virtual void InitSize(int w, int h); //##Documentation //## @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); //##Documentation //## @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); /** * \deprecatedSince{2013_09} Please use TimeGeometry instead of TimeSlicedGeometry. For more information see * http://www.mitk.org/Development/Refactoring%20of%20the%20Geometry%20Classes%20-%20Part%201 */ DEPRECATED(void SetWorldGeometry3D(TimeSlicedGeometry *geometry)); itkGetConstObjectMacro(WorldTimeGeometry, TimeGeometry) //##Documentation //## @brief Get the current 3D-worldgeometry (m_CurrentWorldGeometry) used for 3D-rendering itkGetConstObjectMacro(CurrentWorldGeometry, BaseGeometry) //##Documentation //## @brief Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering itkGetConstObjectMacro(CurrentWorldPlaneGeometry, PlaneGeometry) /** * \deprecatedSince{2014_10} Please use GetCurrentWorldPlaneGeometry */ DEPRECATED(const PlaneGeometry *GetCurrentWorldGeometry2D()) { return GetCurrentWorldPlaneGeometry(); }; //##Documentation //## 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. //## \warn This is not implemented yet. virtual bool SetWorldGeometryToDataStorageBounds() { return false; } //##Documentation //## @brief Set/Get m_Slice which defines together with m_TimeStep the 2D geometry //## stored in m_WorldTimeGeometry used as m_CurrentWorldPlaneGeometry //## //## \sa m_Slice virtual void SetSlice(unsigned int slice); itkGetConstMacro(Slice, unsigned int) //##Documentation //## @brief Set/Get m_TimeStep which defines together with m_Slice the 2D geometry //## stored in m_WorldTimeGeometry used as m_CurrentWorldPlaneGeometry //## //## \sa m_TimeStep virtual void SetTimeStep(unsigned int timeStep); itkGetConstMacro(TimeStep, unsigned int) //##Documentation //## @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. //## \sa GetTimeStep, m_TimeStep int GetTimeStep(const BaseData *data) const; //##Documentation //## @brief Get the time in ms of the currently displayed content //## //## \sa GetTimeStep, m_TimeStep ScalarType GetTime() const; //##Documentation //## @brief SetWorldGeometry is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometrySendEvent virtual void SetGeometry(const itk::EventObject &geometrySliceEvent); //##Documentation //## @brief UpdateWorldGeometry is called to re-read the 2D geometry from the //## slice navigation controller virtual void UpdateGeometry(const itk::EventObject &geometrySliceEvent); //##Documentation //## @brief SetSlice is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometrySliceEvent virtual void SetGeometrySlice(const itk::EventObject &geometrySliceEvent); //##Documentation //## @brief SetTimeStep is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometryTimeEvent virtual void SetGeometryTime(const itk::EventObject &geometryTimeEvent); //##Documentation //## @brief Get a DataNode pointing to a data object containing the current 2D-worldgeometry // m_CurrentWorldPlaneGeometry (for 2D rendering) itkGetObjectMacro(CurrentWorldPlaneGeometryNode, DataNode) /** * \deprecatedSince{2014_10} Please use GetCurrentWorldPlaneGeometryNode */ DEPRECATED(DataNode *GetCurrentWorldGeometry2DNode()) { return GetCurrentWorldPlaneGeometryNode(); }; //##Documentation //## @brief Sets timestamp of CurrentWorldPlaneGeometry and forces so reslicing in that renderwindow void SendUpdateSlice(); //##Documentation //## @brief Get timestamp of last call of SetCurrentWorldPlaneGeometry unsigned long GetCurrentWorldPlaneGeometryUpdateTime() { return m_CurrentWorldPlaneGeometryUpdateTime; } /** * \deprecatedSince{2014_10} Please use GetCurrentWorldPlaneGeometryUpdateTime */ DEPRECATED(unsigned long GetCurrentWorldGeometry2DUpdateTime()) { return GetCurrentWorldPlaneGeometryUpdateTime(); }; //##Documentation //## @brief Get timestamp of last change of current TimeStep unsigned long GetTimeStepUpdateTime() { return m_TimeStepUpdateTime; } //##Documentation //## @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 { return nullptr; } //##Documentation //## @brief Get the MapperSlotId to use. itkGetMacro(MapperID, MapperSlotId) itkGetConstMacro(MapperID, MapperSlotId) //##Documentation //## @brief Set the MapperSlotId to use. itkSetMacro(MapperID, MapperSlotId) virtual int *GetSize() const; virtual int *GetViewportSize() const; void SetSliceNavigationController(SliceNavigationController *SlicenavigationController); itkGetObjectMacro(CameraController, CameraController) itkGetObjectMacro(SliceNavigationController, SliceNavigationController) itkGetObjectMacro(CameraRotationController, CameraRotationController) itkGetMacro(EmptyWorldGeometry, bool) //##Documentation //## @brief Tells if the displayed region is shifted and rescaled if the render window is resized. itkGetMacro(KeepDisplayedRegion, bool) //##Documentation //## @brief Tells if the displayed region should be shifted and rescaled if the render window is resized. itkSetMacro(KeepDisplayedRegion, bool) //##Documentation //## @brief get the name of the Renderer //## @note const char *GetName() const { return m_Name.c_str(); } //##Documentation //## @brief get the x_size of the RendererWindow //## @note int GetSizeX() const { return GetSize()[0]; } //##Documentation //## @brief get the y_size of the RendererWindow //## @note int GetSizeY() const { return GetSize()[1]; } const double *GetBounds() const; void RequestUpdate(); void ForceImmediateUpdate(); /** Returns number of mappers which are visible and have level-of-detail * rendering enabled */ unsigned int GetNumberOfVisibleLODEnabledMappers() const; ///** //* \brief Setter for the RenderingManager that handles this instance of BaseRenderer //*/ // void SetRenderingManager( mitk::RenderingManager* ); /** * \brief Getter for the RenderingManager that handles this instance of BaseRenderer */ virtual mitk::RenderingManager *GetRenderingManager() const; //##Documentation //## @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; //##Documentation //## @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; //##Documentation //## @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; //##Documentation //## @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; //##Documentation //## @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; //##Documentation //## @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; double GetScaleFactorMMPerDisplayUnit() const; Point2D GetDisplaySizeInMM() const; Point2D GetViewportSizeInMM() const; Point2D GetOriginInMM() const; itkGetConstMacro(ConstrainZoomingAndPanning, bool) virtual void SetConstrainZoomingAndPanning(bool constrain); /** * \brief Provides (1) world coordinates for a given mouse position and (2) * translates mousePosition to Display coordinates * \deprecated Map2DRendererPositionTo3DWorldPosition is deprecated. Please use DisplayToWorld instead. */ DEPRECATED(virtual Point3D Map2DRendererPositionTo3DWorldPosition(const Point2D &mousePosition) const); protected: ~BaseRenderer() override; //##Documentation //## @brief Call update of all mappers. To be implemented in subclasses. virtual void Update() = 0; vtkRenderWindow *m_RenderWindow; vtkRenderer *m_VtkRenderer; //##Documentation //## @brief MapperSlotId to use. Defines which kind of mapper (e.g., 2D or 3D) shoud be used. MapperSlotId m_MapperID; //##Documentation //## @brief The DataStorage that is used for rendering. DataStorage::Pointer m_DataStorage; //##Documentation //## @brief The RenderingManager that manages this instance RenderingManager::Pointer m_RenderingManager; //##Documentation //## @brief Timestamp of last call of Update(). unsigned long m_LastUpdateTime; //##Documentation //## @brief CameraController for 3D rendering //## @note preliminary. itk::SmartPointer m_CameraController; SliceNavigationController::Pointer m_SliceNavigationController; CameraRotationController::Pointer m_CameraRotationController; //##Documentation //## @brief Sets m_CurrentWorldPlaneGeometry virtual void SetCurrentWorldPlaneGeometry(const PlaneGeometry *geometry2d); /** * \deprecatedSince{2014_10} Please use SetCurrentWorldPlaneGeometry */ DEPRECATED(void SetCurrentWorldGeometry2D(PlaneGeometry *geometry2d)) { SetCurrentWorldPlaneGeometry(geometry2d); }; //##Documentation //## @brief Sets m_CurrentWorldGeometry virtual void SetCurrentWorldGeometry(const BaseGeometry *geometry); private: //##Documentation //## 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 TimeGeometry::ConstPointer m_WorldTimeGeometry; //##Documentation //## Pointer to the current 3D-worldgeometry. BaseGeometry::ConstPointer m_CurrentWorldGeometry; //##Documentation //## 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). PlaneGeometry::Pointer m_CurrentWorldPlaneGeometry; //##Documentation //## 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_Slice; //##Documentation //## 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_TimeStep; //##Documentation //## @brief timestamp of last call of SetWorldGeometry itk::TimeStamp m_CurrentWorldPlaneGeometryUpdateTime; //##Documentation //## @brief timestamp of last change of the current time step itk::TimeStamp m_TimeStepUpdateTime; //##Documentation //## @brief Helper class which establishes connection between Interactors and Dispatcher via a common DataStorage. BindDispatcherInteractor *m_BindDispatcherInteractor; //##Documentation //## @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; //##Documentation //## Data object containing the m_CurrentWorldPlaneGeometry defined above. PlaneGeometryData::Pointer m_CurrentWorldPlaneGeometryData; //##Documentation //## DataNode objects containing the m_CurrentWorldPlaneGeometryData defined above. DataNode::Pointer m_CurrentWorldPlaneGeometryNode; //##Documentation //## @brief test only unsigned long m_CurrentWorldPlaneGeometryTransformTime; std::string m_Name; double m_Bounds[6]; bool m_EmptyWorldGeometry; 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 protected: std::list m_RegisteredLocalStorageHandlers; bool m_ConstrainZoomingAndPanning; public: void RemoveAllLocalStorages(); void RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh); void UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh); }; } // namespace mitk #endif /* BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 */ diff --git a/Modules/Core/include/mitkRenderWindow.h b/Modules/Core/include/mitkRenderWindow.h index fe2522dfbd..29fe7911ac 100644 --- a/Modules/Core/include/mitkRenderWindow.h +++ b/Modules/Core/include/mitkRenderWindow.h @@ -1,100 +1,99 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66ASDF #define MITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66ASDF #include #include "mitkRenderWindowBase.h" namespace mitk { class vtkEventProvider; /** * \brief mitkRenderWindow integrates the MITK rendering mechanism into VTK and * is NOT QT dependent * * * \ingroup Renderer */ class MITKCORE_EXPORT RenderWindow : public mitk::RenderWindowBase, public itk::Object { public: mitkClassMacroItkParent(RenderWindow, itk::Object); itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitkNewMacro1Param(Self, vtkRenderWindow *); mitkNewMacro2Param(Self, vtkRenderWindow *, const char *); - mitkNewMacro3Param(Self, vtkRenderWindow *, const char *, mitk::RenderingManager *); - mitkNewMacro4Param( - Self, vtkRenderWindow *, const char *, mitk::RenderingManager *, mitk::BaseRenderer::RenderingMode::Type); + mitkNewMacro3Param(Self, vtkRenderWindow *, const char *, RenderingManager *); + mitkNewMacro4Param(Self, vtkRenderWindow *, const char *, RenderingManager *, BaseRenderer::RenderingMode); ~RenderWindow() override; vtkRenderWindow *GetVtkRenderWindow() override; vtkRenderWindowInteractor *GetVtkRenderWindowInteractor() override; // Set Layout Index to define the Layout Type void SetLayoutIndex(unsigned int layoutIndex); // Get Layout Index to define the Layout Type unsigned int GetLayoutIndex(); // MenuWidget need to update the Layout Design List when Layout had changed void LayoutDesignListChanged(int layoutDesignIndex); void FullScreenMode(bool state); /** * \brief Convenience method to set the size of an mitkRenderWindow. * * This method sets the size of the vtkRenderWindow and tells the * rendering that the size has changed -> adapts displayGeometry, etc. */ void SetSize(int width, int height); /** * \brief Initializes the mitkVtkEventProvider to listen to the * currently used vtkInteractorStyle. * * This method makes sure that the internal mitkVtkEventProvider * listens to the correct vtkInteractorStyle. * This makes sure that VTK-Events are correctly translated into * MITK-Events. * * \warn This method needs to be called MANUALLY as soon as the MapperID * for this RenderWindow is changed or the vtkInteractorStyle is modified * somehow else! */ void ReinitEventProvider(); protected: RenderWindow(vtkRenderWindow *existingRenderWindow = nullptr, const char *name = "unnamed renderer", - mitk::RenderingManager *rm = nullptr, - mitk::BaseRenderer::RenderingMode::Type rmtype = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing); + RenderingManager *rm = nullptr, + BaseRenderer::RenderingMode rmtype = BaseRenderer::RenderingMode::FastApproximateAntiAliasing); void ResetView(); vtkRenderWindow *m_vtkRenderWindow; vtkRenderWindowInteractor *m_vtkRenderWindowInteractor; vtkEventProvider *m_vtkMitkEventProvider; private: }; } // namespace #endif /* MITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66ASDF */ diff --git a/Modules/Core/include/mitkRenderWindowBase.h b/Modules/Core/include/mitkRenderWindowBase.h index ef2a23e442..a56f2b6b42 100644 --- a/Modules/Core/include/mitkRenderWindowBase.h +++ b/Modules/Core/include/mitkRenderWindowBase.h @@ -1,83 +1,83 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKRENDERWINDOWBASE_H_HEADER_INCLUDED_C1C40D66ASDF #define MITKRENDERWINDOWBASE_H_HEADER_INCLUDED_C1C40D66ASDF #include #include "mitkCameraRotationController.h" #include "mitkSliceNavigationController.h" #include "mitkVtkPropRenderer.h" #include "vtkMitkRenderProp.h" #include "mitkInteractionEvent.h" namespace mitk { /** * \brief Base class of MITK RenderWindows * * This class sets up the MITK rendering mechanism and it's integration into VTK. * * Currently, there are two specific implementations of this abstract class: * QmitkRenderWindow, inerhits from the QVTKWidget and is the matured way for MITK rendering * mitkRenderWindow is a new, QT-independent RenderWindow implementation * * \ingroup Renderer */ class MITKCORE_EXPORT RenderWindowBase { public: // mitkClassMacroItkParent(RenderWindowBase,itk::Object); // itkFactorylessNewMacro(Self) // itkCloneMacro(Self) virtual ~RenderWindowBase(); void InitRenderer(); virtual mitk::SliceNavigationController *GetSliceNavigationController(); virtual mitk::CameraRotationController *GetCameraRotationController(); virtual mitk::BaseController *GetController(); virtual mitk::VtkPropRenderer *GetRenderer(); virtual vtkRenderWindow *GetVtkRenderWindow() = 0; virtual vtkRenderWindowInteractor *GetVtkRenderWindowInteractor() = 0; virtual bool HandleEvent(InteractionEvent *interactionEvent); protected: RenderWindowBase(); // helper functions: within constructors and destructors classes are not polymorph. void Initialize( - mitk::RenderingManager *renderingManager = nullptr, + RenderingManager *renderingManager = nullptr, const char *name = "unnamed renderer", - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing); + BaseRenderer::RenderingMode renderingMode = BaseRenderer::RenderingMode::FastApproximateAntiAliasing); void Destroy(); mitk::VtkPropRenderer::Pointer m_Renderer; vtkMitkRenderProp *m_RenderProp; bool m_InResize; private: }; } #endif /* MITKRENDERWINDOWBASE_H_HEADER_INCLUDED_C1C40D66ASDF */ diff --git a/Modules/Core/include/mitkVtkPropRenderer.h b/Modules/Core/include/mitkVtkPropRenderer.h index 5eeae29d8f..28b7738229 100644 --- a/Modules/Core/include/mitkVtkPropRenderer.h +++ b/Modules/Core/include/mitkVtkPropRenderer.h @@ -1,258 +1,258 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkVtkPropRenderer_h #define mitkVtkPropRenderer_h #include "mitkBaseRenderer.h" #include #include #include #include #include #include class vtkRenderWindow; class vtkLight; class vtkLightKit; class vtkWorldPointPicker; class vtkPointPicker; class vtkCellPicker; class vtkTextActor; class vtkTextProperty; class vtkAssemblyPath; #include #include namespace mitk { class Mapper; /*! \brief VtkPropRenderer VtkPropRenderer organizes the MITK rendering process. The MITK rendering process is completely integrated into the VTK rendering pipeline. The vtkMitkRenderProp is a custom vtkProp derived class, which implements the rendering interface between MITK and VTK. It redirects render() calls to the VtkPropRenderer, which is responsible for rendering of the datatreenodes. VtkPropRenderer replaces the old OpenGLRenderer. \sa rendering \ingroup rendering */ class MITKCORE_EXPORT VtkPropRenderer : public BaseRenderer { // Workaround for Displaylistbug private: bool didCount; void checkState(); // Workaround END public: mitkClassMacro(VtkPropRenderer, BaseRenderer); mitkNewMacro3Param(VtkPropRenderer, const char *, vtkRenderWindow *, mitk::RenderingManager *); mitkNewMacro4Param(VtkPropRenderer, const char *, vtkRenderWindow *, mitk::RenderingManager *, - mitk::BaseRenderer::RenderingMode::Type); + mitk::BaseRenderer::RenderingMode); typedef std::map MappersMapType; // Render - called by vtkMitkRenderProp, returns the number of props rendered enum RenderType { Opaque, Translucent, Overlay, Volumetric }; /** \brief Store/propagate vtkInformation during rendering */ void SetPropertyKeys(vtkInformation *info); int Render(RenderType type); /** \brief This methods contains all method neceassary before a VTK Render() call */ virtual void PrepareRender(); // Active current renderwindow virtual void MakeCurrent(); void SetDataStorage( mitk::DataStorage *storage) override; ///< set the datastorage that will be used for rendering void InitRenderer(vtkRenderWindow *renderwindow) override; virtual void Update(mitk::DataNode *datatreenode); void SetMapperID(const MapperSlotId mapperId) override; // Size void InitSize(int w, int h) override; void Resize(int w, int h) override; // Picking enum PickingMode { WorldPointPicking, PointPicking, CellPicking }; /** \brief Set the picking mode. This method is used to set the picking mode for 3D object picking. The user can select one of the three options WorldPointPicking, PointPicking and CellPicking. The first option uses the zBuffer from graphics rendering, the second uses the 3D points from the closest surface mesh, and the third option uses the cells of that mesh. The last option is the slowest, the first one the fastest. However, the first option cannot use transparent data object and the tolerance of the picked position to the selected point should be considered. PointPicking also need a tolerance around the picking position to select the closest point in the mesh. The CellPicker performs very well, if the foreground surface part (i.e. the surfacepart that is closest to the scene's cameras) needs to be picked. */ itkSetEnumMacro(PickingMode, PickingMode); itkGetEnumMacro(PickingMode, PickingMode); void PickWorldPoint(const Point2D &displayPoint, Point3D &worldPoint) const override; mitk::DataNode *PickObject(const Point2D &displayPosition, Point3D &worldPosition) const override; /** * @brief WriteSimpleText Write a text in a renderwindow. * * Writes some 2D text as overlay. Function returns an unique int Text_ID for each call, which can be used via the GetTextLabelProperty(int text_id) function in order to get a vtkTextProperty. This property enables the setup of font, font size, etc. * * @deprecatedSince{2015_05} Please use mitkTextOverlay2D instead. * See mitkTextOverlay2DRenderingTest for an example. */ DEPRECATED(int WriteSimpleText(std::string text, double posX, double posY, double color1 = 0.0, double color2 = 1.0, double color3 = 0.0, float opacity = 1.0)); /** * @brief CGetTextLabelProperty an be used in order to get a vtkTextProperty for * a specific text_id. This property enables the setup of font, font size, etc. * @param text_id the id of the text property. * @deprecatedSince{2015_05} Please use mitkTextOverlay2D instead. * See mitkTextOverlay2DRenderingTest for an example. */ DEPRECATED(vtkTextProperty *GetTextLabelProperty(int text_id)); /** This method 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. */ bool SetWorldGeometryToDataStorageBounds() override; /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ void InitPathTraversal(); /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ vtkAssemblyPath *GetNextPath(); int GetNumberOfPaths(); const vtkWorldPointPicker *GetWorldPointPicker() const; const vtkPointPicker *GetPointPicker() const; const vtkCellPicker *GetCellPicker() const; /** * \brief Release vtk-based graphics resources. Called by * vtkMitkRenderProp::ReleaseGraphicsResources. */ virtual void ReleaseGraphicsResources(vtkWindow *renWin); MappersMapType GetMappersMap() const; static bool useImmediateModeRendering(); protected: VtkPropRenderer( const char *name = "VtkPropRenderer", vtkRenderWindow *renWin = nullptr, mitk::RenderingManager *rm = nullptr, - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing); + mitk::BaseRenderer::RenderingMode renderingMode = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing); ~VtkPropRenderer() override; void Update() override; static void RenderingCallback(vtkObject *caller, unsigned long eid, void *clientdata, void *calldata); virtual void UpdatePaths(); // apply transformations and properties recursively private: vtkSmartPointer m_Paths; vtkTimeStamp m_PathTime; // prepare all mitk::mappers for rendering void PrepareMapperQueue(); /** \brief Propagate vtkInformation object to all VTK-based mappers */ void PropagateRenderInfoToMappers(); /** \brief Set parallel projection, remove the interactor and the lights of VTK. */ bool Initialize2DvtkCamera(); bool m_InitNeeded; bool m_ResizeNeeded; MapperSlotId m_CameraInitializedForMapperID; // Picking vtkWorldPointPicker *m_WorldPointPicker; vtkPointPicker *m_PointPicker; vtkCellPicker *m_CellPicker; PickingMode m_PickingMode; // Explicit use of SmartPointer to avoid circular #includes itk::SmartPointer m_CurrentWorldPlaneGeometryMapper; vtkLightKit *m_LightKit; // sorted list of mappers MappersMapType m_MappersMap; // rendering of text vtkRenderer *m_TextRenderer; typedef std::map TextMapType; TextMapType m_TextCollection; /** \brief Information passed from VTK's rendering to props. Used e.g. by vtkDualDepthPeelingPass to pass information. Not passing this to all the MITK generated vktProps will essentially break VTK's depth peeling / transparency. */ vtkInformation* m_VtkRenderInfo = nullptr; }; } // namespace mitk #endif /* mitkVtkPropRenderer_h */ diff --git a/Modules/Core/src/Rendering/mitkBaseRenderer.cpp b/Modules/Core/src/Rendering/mitkBaseRenderer.cpp index b7fec9d925..ed9225bacc 100644 --- a/Modules/Core/src/Rendering/mitkBaseRenderer.cpp +++ b/Modules/Core/src/Rendering/mitkBaseRenderer.cpp @@ -1,787 +1,787 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #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 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, mitk::RenderingManager *rm, - RenderingMode::Type renderingMode) + RenderingMode renderingMode) : m_RenderWindow(nullptr), m_VtkRenderer(nullptr), m_MapperID(defaultMapper), m_DataStorage(nullptr), m_RenderingManager(rm), 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->ConnectGeometrySliceEvent(this); sliceNavigationController->ConnectGeometryUpdateEvent(this); sliceNavigationController->ConnectGeometryTimeEvent(this, false); 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->UseDepthPeelingOn(); m_VtkRenderer->UseDepthPeelingForVolumesOn(); m_VtkRenderer->SetMaximumNumberOfPeels(16); // This could be made adjustable in the Preferences m_VtkRenderer->SetOcclusionRatio(0.0); if (RenderingMode::FastApproximateAntiAliasing == renderingMode) 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::RemoveAllLocalStorages() { this->InvokeEvent(mitk::BaseRenderer::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() { } void mitk::BaseRenderer::Resize(int w, int h) { this->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); } void mitk::BaseRenderer::SetSlice(unsigned int 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(); } } void mitk::BaseRenderer::SetTimeStep(unsigned int 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(); } } int 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) { assert(geometry != nullptr); itkDebugMacro("setting WorldTimeGeometry to " << geometry); if (m_WorldTimeGeometry != geometry) { 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); } } void mitk::BaseRenderer::SetWorldGeometry3D(const mitk::BaseGeometry *geometry) { itkDebugMacro("setting WorldGeometry3D to " << geometry); if (geometry->GetBoundingBox()->GetDiagonalLength2() == 0) return; const SlicedGeometry3D *slicedWorldGeometry; slicedWorldGeometry = dynamic_cast(geometry); PlaneGeometry::ConstPointer geometry2d; if (slicedWorldGeometry != nullptr) { 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); } else { geometry2d = dynamic_cast(geometry); if (geometry2d.IsNull()) { PlaneGeometry::Pointer plane = PlaneGeometry::New(); plane->InitializeStandardPlane(geometry); geometry2d = plane; } SetCurrentWorldGeometry(geometry); } SetCurrentWorldPlaneGeometry(geometry2d); // calls Modified() if (m_CurrentWorldPlaneGeometry.IsNull()) itkWarningMacro("m_CurrentWorldPlaneGeometry is nullptr"); } 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) { const auto *sendEvent = dynamic_cast(&geometrySendEvent); assert(sendEvent != nullptr); SetWorldTimeGeometry(sendEvent->GetTimeGeometry()); } void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject &geometryUpdateEvent) { const auto *updateEvent = dynamic_cast(&geometryUpdateEvent); if (updateEvent == nullptr) return; if (m_CurrentWorldGeometry.IsNotNull()) { auto *slicedWorldGeometry = dynamic_cast(m_CurrentWorldGeometry.GetPointer()); if (slicedWorldGeometry) { PlaneGeometry *geometry2D = slicedWorldGeometry->GetPlaneGeometry(m_Slice); SetCurrentWorldPlaneGeometry(geometry2D); // calls Modified() } } } void mitk::BaseRenderer::SetGeometrySlice(const itk::EventObject &geometrySliceEvent) { const auto *sliceEvent = dynamic_cast(&geometrySliceEvent); assert(sliceEvent != nullptr); SetSlice(sliceEvent->GetPos()); } void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject &geometryTimeEvent) { const auto *timeEvent = dynamic_cast(&geometryTimeEvent); assert(timeEvent != nullptr); SetTimeStep(timeEvent->GetPos()); } 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); m_RenderingManager->RequestUpdate(this->m_RenderWindow); } void mitk::BaseRenderer::ForceImmediateUpdate() { m_RenderingManager->ForceImmediateUpdate(this->m_RenderWindow); } unsigned int mitk::BaseRenderer::GetNumberOfVisibleLODEnabledMappers() const { return m_NumberOfVisibleLODEnabledMappers; } mitk::RenderingManager *mitk::BaseRenderer::GetRenderingManager() const { return m_RenderingManager.GetPointer(); } /*! 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->ConnectGeometrySliceEvent(this); m_SliceNavigationController->ConnectGeometryUpdateEvent(this); m_SliceNavigationController->ConnectGeometryTimeEvent(this, false); } } void mitk::BaseRenderer::DisplayToWorld(const Point2D &displayPoint, Point3D &worldIndex) const { if (m_MapperID == BaseRenderer::Standard2D) { 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 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. } 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); } 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); this->WorldToDisplay(worldPoint, displayPoint); return; } void mitk::BaseRenderer::PlaneToView(const Point2D &planePointInMM, Point2D &viewPoint) const { Point3D worldPoint; this->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(); } } mitk::Point3D mitk::BaseRenderer::Map2DRendererPositionTo3DWorldPosition(const Point2D &mousePosition) const { // DEPRECATED: Map2DRendererPositionTo3DWorldPosition is deprecated. use DisplayToWorldInstead Point3D position; DisplayToWorld(mousePosition, position); return position; } 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); } diff --git a/Modules/Core/src/Rendering/mitkRenderWindow.cpp b/Modules/Core/src/Rendering/mitkRenderWindow.cpp index d223aa6350..cb9d75a1c1 100644 --- a/Modules/Core/src/Rendering/mitkRenderWindow.cpp +++ b/Modules/Core/src/Rendering/mitkRenderWindow.cpp @@ -1,87 +1,87 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRenderWindow.h" #include "mitkRenderingManager.h" #include "mitkVtkEventProvider.h" #include "mitkVtkLayerController.h" #include "vtkRenderWindowInteractor.h" #include "vtkRenderer.h" mitk::RenderWindow::RenderWindow(vtkRenderWindow *renWin, const char *name, mitk::RenderingManager *rm, - mitk::BaseRenderer::RenderingMode::Type rmtype) + mitk::BaseRenderer::RenderingMode renderingMode) : m_vtkRenderWindow(renWin), m_vtkRenderWindowInteractor(nullptr), m_vtkMitkEventProvider(nullptr) { if (nullptr == m_vtkRenderWindow) { m_vtkRenderWindow = vtkRenderWindow::New(); m_vtkRenderWindow->SetMultiSamples(0); // We do not support MSAA as it is incompatible with depth peeling m_vtkRenderWindow->SetAlphaBitPlanes(1); // Necessary for depth peeling } if (m_vtkRenderWindow->GetSize()[0] <= 10) { m_vtkRenderWindow->SetSize(100, 100); } m_vtkRenderWindowInteractor = vtkRenderWindowInteractor::New(); m_vtkRenderWindowInteractor->SetRenderWindow(m_vtkRenderWindow); m_vtkRenderWindowInteractor->Initialize(); // initialize from RenderWindowBase - this->Initialize(rm, name, rmtype); + this->Initialize(rm, name, renderingMode); m_vtkMitkEventProvider = vtkEventProvider::New(); m_vtkMitkEventProvider->SetInteractor(this->GetVtkRenderWindowInteractor()); m_vtkMitkEventProvider->SetMitkRenderWindow(this); m_vtkMitkEventProvider->SetEnabled(1); } mitk::RenderWindow::~RenderWindow() { Destroy(); m_vtkRenderWindow->Delete(); m_vtkRenderWindowInteractor->Delete(); m_vtkMitkEventProvider->Delete(); } vtkRenderWindow *mitk::RenderWindow::GetVtkRenderWindow() { return m_vtkRenderWindow; } vtkRenderWindowInteractor *mitk::RenderWindow::GetVtkRenderWindowInteractor() { return m_vtkRenderWindowInteractor; } void mitk::RenderWindow::SetSize(int width, int height) { this->GetVtkRenderWindow()->SetSize(width, height); } void mitk::RenderWindow::ReinitEventProvider() { m_vtkMitkEventProvider->SetEnabled(0); m_vtkMitkEventProvider->SetInteractor(this->GetVtkRenderWindowInteractor()); m_vtkMitkEventProvider->SetMitkRenderWindow(this); m_vtkMitkEventProvider->SetEnabled(1); } diff --git a/Modules/Core/src/Rendering/mitkRenderWindowBase.cpp b/Modules/Core/src/Rendering/mitkRenderWindowBase.cpp index a405703343..64ba922ed5 100644 --- a/Modules/Core/src/Rendering/mitkRenderWindowBase.cpp +++ b/Modules/Core/src/Rendering/mitkRenderWindowBase.cpp @@ -1,117 +1,117 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRenderWindowBase.h" #include "mitkRenderingManager.h" #include "mitkVtkLayerController.h" #include "vtkRenderer.h" #include "mitkAnnotationUtils.h" mitk::RenderWindowBase::RenderWindowBase() : m_RenderProp(nullptr), m_InResize(false) { } /* * "Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2). When a * virtual function is called directly or indirectly from a constructor (including from the mem-initializer for a data member) or from * a destructor, and the object to which the call applies is the object under construction or destruction, the function called is * the one defined in the constructor or destructor's own class or in one of its bases, but not a function overriding it in a class * derived from the constructor or destructor's class, or overriding it in one of the other base classes of the most derived object[..]" * or short: within constructors and destructors classes are not polymorph. */ void mitk::RenderWindowBase::Initialize(mitk::RenderingManager *renderingManager, const char *name, - mitk::BaseRenderer::RenderingMode::Type renderingMode) + mitk::BaseRenderer::RenderingMode renderingMode) { if (nullptr == renderingManager) renderingManager = mitk::RenderingManager::GetInstance(); if (m_Renderer.IsNull()) m_Renderer = mitk::VtkPropRenderer::New(name, GetVtkRenderWindow(), renderingManager, renderingMode); m_Renderer->InitRenderer(this->GetVtkRenderWindow()); mitk::BaseRenderer::AddInstance(GetVtkRenderWindow(), m_Renderer); renderingManager->AddRenderWindow(GetVtkRenderWindow()); // Add previously created overlays to new BaseRenderer mitk::AnnotationUtils::BaseRendererChanged(m_Renderer); m_RenderProp = vtkMitkRenderProp::New(); m_RenderProp->SetPropRenderer(m_Renderer); m_Renderer->GetVtkRenderer()->AddViewProp(m_RenderProp); if ((this->GetVtkRenderWindow()->GetSize()[0] > 10) && (this->GetVtkRenderWindow()->GetSize()[1] > 10)) m_Renderer->InitSize(this->GetVtkRenderWindow()->GetSize()[0], this->GetVtkRenderWindow()->GetSize()[1]); m_InResize = false; } bool mitk::RenderWindowBase::HandleEvent(InteractionEvent *interactionEvent) { return m_Renderer->GetDispatcher()->ProcessEvent(interactionEvent); } void mitk::RenderWindowBase::Destroy() { m_Renderer->GetRenderingManager()->RemoveRenderWindow(GetVtkRenderWindow()); m_Renderer->GetVtkRenderer()->RemoveViewProp(m_RenderProp); m_RenderProp->Delete(); BaseRenderer::RemoveInstance(this->GetVtkRenderWindow()); } mitk::RenderWindowBase::~RenderWindowBase() { } mitk::SliceNavigationController *mitk::RenderWindowBase::GetSliceNavigationController() { return mitk::BaseRenderer::GetInstance(this->GetVtkRenderWindow())->GetSliceNavigationController(); } mitk::CameraRotationController *mitk::RenderWindowBase::GetCameraRotationController() { return mitk::BaseRenderer::GetInstance(this->GetVtkRenderWindow())->GetCameraRotationController(); } mitk::BaseController *mitk::RenderWindowBase::GetController() { mitk::BaseRenderer *renderer = mitk::BaseRenderer::GetInstance(GetVtkRenderWindow()); switch (renderer->GetMapperID()) { case mitk::BaseRenderer::Standard2D: return GetSliceNavigationController(); case mitk::BaseRenderer::Standard3D: return GetCameraRotationController(); default: return GetSliceNavigationController(); } } mitk::VtkPropRenderer *mitk::RenderWindowBase::GetRenderer() { return m_Renderer; } diff --git a/Modules/Core/src/Rendering/mitkVtkPropRenderer.cpp b/Modules/Core/src/Rendering/mitkVtkPropRenderer.cpp index 6f0986f708..7abccd72a6 100644 --- a/Modules/Core/src/Rendering/mitkVtkPropRenderer.cpp +++ b/Modules/Core/src/Rendering/mitkVtkPropRenderer.cpp @@ -1,715 +1,715 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkVtkPropRenderer.h" // MAPPERS #include "mitkCameraController.h" #include "mitkImageVtkMapper2D.h" #include "mitkMapper.h" #include "mitkPlaneGeometryDataVtkMapper3D.h" #include "mitkVtkMapper.h" #include #include #include #include #include #include #include #include #include #include // VTK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::VtkPropRenderer::VtkPropRenderer(const char *name, vtkRenderWindow *renWin, - mitk::RenderingManager *rm, - mitk::BaseRenderer::RenderingMode::Type renderingMode) + RenderingManager *rm, + BaseRenderer::RenderingMode renderingMode) : BaseRenderer(name, renWin, rm, renderingMode), m_CameraInitializedForMapperID(0) { didCount = false; m_WorldPointPicker = vtkWorldPointPicker::New(); m_PointPicker = vtkPointPicker::New(); m_PointPicker->SetTolerance(0.0025); m_CellPicker = vtkCellPicker::New(); m_CellPicker->SetTolerance(0.0025); mitk::PlaneGeometryDataVtkMapper3D::Pointer geometryMapper = mitk::PlaneGeometryDataVtkMapper3D::New(); m_CurrentWorldPlaneGeometryMapper = geometryMapper; m_CurrentWorldPlaneGeometryNode->SetMapper(2, geometryMapper); m_LightKit = vtkLightKit::New(); m_LightKit->AddLightsToRenderer(m_VtkRenderer); m_PickingMode = WorldPointPicking; m_TextRenderer = vtkRenderer::New(); m_TextRenderer->SetRenderWindow(renWin); m_TextRenderer->SetInteractive(0); m_TextRenderer->SetErase(0); } /*! \brief Destructs the VtkPropRenderer. */ mitk::VtkPropRenderer::~VtkPropRenderer() { // Workaround for GLDisplayList Bug { m_MapperID = 0; checkState(); } if (m_LightKit != nullptr) m_LightKit->Delete(); if (m_VtkRenderer != nullptr) { m_CameraController = nullptr; m_VtkRenderer->Delete(); m_VtkRenderer = nullptr; } else m_CameraController = nullptr; if (m_WorldPointPicker != nullptr) m_WorldPointPicker->Delete(); if (m_PointPicker != nullptr) m_PointPicker->Delete(); if (m_CellPicker != nullptr) m_CellPicker->Delete(); if (m_TextRenderer != nullptr) m_TextRenderer->Delete(); } void mitk::VtkPropRenderer::SetDataStorage(mitk::DataStorage *storage) { if (storage == nullptr || storage == m_DataStorage) return; BaseRenderer::SetDataStorage(storage); static_cast(m_CurrentWorldPlaneGeometryMapper.GetPointer()) ->SetDataStorageForTexture(m_DataStorage.GetPointer()); // Compute the geometry from the current data tree bounds and set it as world geometry this->SetWorldGeometryToDataStorageBounds(); } bool mitk::VtkPropRenderer::SetWorldGeometryToDataStorageBounds() { if (m_DataStorage.IsNull()) return false; // initialize world geometry auto geometry = m_DataStorage->ComputeVisibleBoundingGeometry3D(nullptr, "includeInBoundingBox"); if (geometry.IsNull()) return false; this->SetWorldTimeGeometry(geometry); this->GetVtkRenderer()->ResetCamera(); this->GetCameraController()->Fit(); this->Modified(); return true; } /*! \brief Called by the vtkMitkRenderProp in order to start MITK rendering process. */ int mitk::VtkPropRenderer::Render(mitk::VtkPropRenderer::RenderType type) { // Do we have objects to render? if (this->GetEmptyWorldGeometry()) return 0; if (m_DataStorage.IsNull()) return 0; // Update mappers and prepare mapper queue if (type == VtkPropRenderer::Opaque) { this->PrepareMapperQueue(); // Share vtkInformation, there might be new mappers this->PropagateRenderInfoToMappers(); } // go through the generated list and let the sorted mappers paint for (auto it = m_MappersMap.cbegin(); it != m_MappersMap.cend(); it++) { Mapper *mapper = (*it).second; mapper->MitkRender(this, type); } // Render text if (type == VtkPropRenderer::Overlay) { if (m_TextCollection.size() > 0) { m_TextRenderer->SetViewport(this->GetVtkRenderer()->GetViewport()); for (auto it = m_TextCollection.begin(); it != m_TextCollection.end(); ++it) m_TextRenderer->AddViewProp((*it).second); m_TextRenderer->Render(); } } return 1; } /*! \brief PrepareMapperQueue iterates the datatree PrepareMapperQueue iterates the datatree in order to find mappers which shall be rendered. Also, it sortes the mappers wrt to their layer. */ void mitk::VtkPropRenderer::PrepareMapperQueue() { // variable for counting LOD-enabled mappers m_NumberOfVisibleLODEnabledMappers = 0; // Do we have to update the mappers ? if (m_LastUpdateTime < GetMTime() || m_LastUpdateTime < this->GetCurrentWorldPlaneGeometry()->GetMTime()) { Update(); } else if (m_MapperID >= 1 && m_MapperID < 6) Update(); // remove all text properties before mappers will add new ones m_TextRenderer->RemoveAllViewProps(); for (unsigned int i = 0; i < m_TextCollection.size(); i++) { m_TextCollection[i]->Delete(); } m_TextCollection.clear(); // clear priority_queue m_MappersMap.clear(); int mapperNo = 0; // DataStorage if (m_DataStorage.IsNull()) return; DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for (DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); it != allObjects->End(); ++it) { const DataNode::Pointer node = it->Value(); if (node.IsNull()) continue; const mitk::Mapper::Pointer mapper = node->GetMapper(m_MapperID); if (mapper.IsNull()) continue; bool visible = true; node->GetVisibility(visible, this, "visible"); // The information about LOD-enabled mappers is required by RenderingManager if (mapper->IsLODEnabled(this) && visible) { ++m_NumberOfVisibleLODEnabledMappers; } // mapper without a layer property get layer number 1 int layer = 1; node->GetIntProperty("layer", layer, this); int nr = (layer << 16) + mapperNo; m_MappersMap.insert(std::pair(nr, mapper)); mapperNo++; } } void mitk::VtkPropRenderer::SetPropertyKeys(vtkInformation *info) { if (info == m_VtkRenderInfo) return; m_VtkRenderInfo = info; this->PropagateRenderInfoToMappers(); } void mitk::VtkPropRenderer::PropagateRenderInfoToMappers() { if (m_VtkRenderInfo == nullptr) return; for (const auto &mapEntry : m_MappersMap) { auto vtkMapper = dynamic_cast(mapEntry.second); if (nullptr != vtkMapper) { auto prop = vtkMapper->GetVtkProp(this); if (nullptr != prop) prop->SetPropertyKeys(m_VtkRenderInfo); } } } void mitk::VtkPropRenderer::Update(mitk::DataNode *datatreenode) { if (datatreenode != nullptr) { mitk::Mapper::Pointer mapper = datatreenode->GetMapper(m_MapperID); if (mapper.IsNotNull()) { if (GetCurrentWorldPlaneGeometry()->IsValid()) { mapper->Update(this); { auto *vtkmapper = dynamic_cast(mapper.GetPointer()); if (vtkmapper != nullptr) { vtkmapper->UpdateVtkTransform(this); } } } } } } void mitk::VtkPropRenderer::Update() { if (m_DataStorage.IsNull()) return; mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetAll(); for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) Update(it->Value()); Modified(); m_LastUpdateTime = GetMTime(); } /*! \brief This method is called from the two Constructors */ void mitk::VtkPropRenderer::InitRenderer(vtkRenderWindow *renderWindow) { BaseRenderer::InitRenderer(renderWindow); vtkCallbackCommand *renderCallbackCommand = vtkCallbackCommand::New(); renderCallbackCommand->SetCallback(VtkPropRenderer::RenderingCallback); renderWindow->GetInteractor()->AddObserver(vtkCommand::RenderEvent, renderCallbackCommand); renderCallbackCommand->Delete(); if (renderWindow == nullptr) { m_InitNeeded = false; m_ResizeNeeded = false; return; } m_InitNeeded = true; m_ResizeNeeded = true; m_LastUpdateTime = 0; } void mitk::VtkPropRenderer::RenderingCallback(vtkObject *caller, unsigned long, void *, void *) { auto *renderWindowInteractor = dynamic_cast(caller); if (!renderWindowInteractor) return; mitk::BaseRenderer *renderer = mitk::BaseRenderer::GetInstance(renderWindowInteractor->GetRenderWindow()); if (renderer) renderer->RequestUpdate(); } /*! \brief Resize the OpenGL Window */ void mitk::VtkPropRenderer::Resize(int w, int h) { BaseRenderer::Resize(w, h); m_RenderingManager->RequestUpdate(this->GetRenderWindow()); } void mitk::VtkPropRenderer::InitSize(int w, int h) { m_RenderWindow->SetSize(w, h); Superclass::InitSize(w, h); Modified(); Update(); if (m_VtkRenderer != nullptr) { int w = vtkObject::GetGlobalWarningDisplay(); vtkObject::GlobalWarningDisplayOff(); m_VtkRenderer->ResetCamera(); vtkObject::SetGlobalWarningDisplay(w); } this->GetCameraController()->Fit(); } int mitk::VtkPropRenderer::WriteSimpleText( std::string text, double posX, double posY, double color1, double color2, double color3, float opacity) { this->GetVtkRenderer()->ViewToDisplay(); if (!text.empty()) { Point2D p; vtkTextActor *textActor = vtkTextActor::New(); textActor->SetDisplayPosition(posX, posY); textActor->SetInput(text.c_str()); textActor->SetTextScaleModeToNone(); textActor->GetTextProperty()->SetColor(color1, color2, color3); // TODO: Read color from node property textActor->GetTextProperty()->SetOpacity(opacity); int text_id = m_TextCollection.size(); m_TextCollection.insert(TextMapType::value_type(text_id, textActor)); return text_id; } else { return -1; } } void mitk::VtkPropRenderer::SetMapperID(const MapperSlotId mapperId) { if (m_MapperID != mapperId) Superclass::SetMapperID(mapperId); // Workaround for GL Displaylist Bug checkState(); } /*! \brief Activates the current renderwindow. */ void mitk::VtkPropRenderer::MakeCurrent() { if (m_RenderWindow != nullptr) m_RenderWindow->MakeCurrent(); } void mitk::VtkPropRenderer::PickWorldPoint(const mitk::Point2D &displayPoint, mitk::Point3D &worldPoint) const { if (this->GetRenderWindow()->GetNeverRendered() != 0) return; // somebody called picking before we ever rendered; cannot have enough information yet switch (m_PickingMode) { case (WorldPointPicking): { m_WorldPointPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); vtk2itk(m_WorldPointPicker->GetPickPosition(), worldPoint); break; } case (PointPicking): { m_PointPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); vtk2itk(m_PointPicker->GetPickPosition(), worldPoint); break; } case (CellPicking): { m_CellPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); vtk2itk(m_CellPicker->GetPickPosition(), worldPoint); break; } } // todo: is this picking in 2D renderwindows? // Superclass::PickWorldPoint(displayPoint, worldPoint); } mitk::DataNode *mitk::VtkPropRenderer::PickObject(const Point2D &displayPosition, Point3D &worldPosition) const { m_CellPicker->InitializePickList(); // Iterate over all DataStorage objects to determine all vtkProps intended // for picking DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for (DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); it != allObjects->End(); ++it) { const DataNode *node = it->Value(); if (node == nullptr) continue; bool pickable = false; node->GetBoolProperty("pickable", pickable); if (!pickable) continue; auto *mapper = dynamic_cast(node->GetMapper(m_MapperID)); if (mapper == nullptr) continue; vtkProp *prop = mapper->GetVtkProp((mitk::BaseRenderer *)this); if (prop == nullptr) continue; m_CellPicker->AddPickList(prop); } // Do the picking and retrieve the picked vtkProp (if any) m_CellPicker->PickFromListOn(); m_CellPicker->Pick(displayPosition[0], displayPosition[1], 0.0, m_VtkRenderer); m_CellPicker->PickFromListOff(); vtk2itk(m_CellPicker->GetPickPosition(), worldPosition); vtkProp *prop = m_CellPicker->GetViewProp(); if (prop == nullptr) { return nullptr; } // Iterate over all DataStorage objects to determine if the retrieved // vtkProp is owned by any associated mapper. for (DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); it != allObjects->End(); ++it) { DataNode::Pointer node = it->Value(); if (node.IsNull()) continue; mitk::Mapper *mapper = node->GetMapper(m_MapperID); if (mapper == nullptr) continue; auto *vtkmapper = dynamic_cast(mapper); if (vtkmapper) { // if vtk-based, then ... if (vtkmapper->HasVtkProp(prop, const_cast(this))) { return node; } } } return nullptr; } // todo: is this 2D renderwindow picking? // return Superclass::PickObject( displayPosition, worldPosition ); vtkTextProperty *mitk::VtkPropRenderer::GetTextLabelProperty(int text_id) { return this->m_TextCollection[text_id]->GetTextProperty(); } void mitk::VtkPropRenderer::InitPathTraversal() { if (m_DataStorage.IsNotNull()) { this->UpdatePaths(); this->m_Paths->InitTraversal(); } } void mitk::VtkPropRenderer::UpdatePaths() { if (m_DataStorage.IsNull()) { return; } if (GetMTime() > m_PathTime || (m_Paths != nullptr && m_Paths->GetMTime() > m_PathTime)) { // Create the list to hold all the paths m_Paths = vtkSmartPointer::New(); DataStorage::SetOfObjects::ConstPointer objects = m_DataStorage->GetAll(); for (auto iter = objects->begin(); iter != objects->end(); ++iter) { vtkSmartPointer onePath = vtkSmartPointer::New(); Mapper *mapper = (*iter)->GetMapper(BaseRenderer::Standard3D); if (mapper) { auto *vtkmapper = dynamic_cast(mapper); if (nullptr != vtkmapper) { vtkProp *prop = vtkmapper->GetVtkProp(this); if (prop && prop->GetVisibility()) { // add to assembly path onePath->AddNode(prop, prop->GetMatrix()); m_Paths->AddItem(onePath); } } } } m_PathTime.Modified(); } } int mitk::VtkPropRenderer::GetNumberOfPaths() { UpdatePaths(); return m_Paths->GetNumberOfItems(); } vtkAssemblyPath *mitk::VtkPropRenderer::GetNextPath() { return m_Paths ? m_Paths->GetNextItem() : nullptr; } void mitk::VtkPropRenderer::ReleaseGraphicsResources(vtkWindow * /*renWin*/) { if (m_DataStorage.IsNull()) return; DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for (auto iter = allObjects->begin(); iter != allObjects->end(); ++iter) { DataNode::Pointer node = *iter; if (node.IsNull()) continue; Mapper *mapper = node->GetMapper(m_MapperID); if (mapper) { auto *vtkmapper = dynamic_cast(mapper); if (vtkmapper) vtkmapper->ReleaseGraphicsResources(this); } } } const vtkWorldPointPicker *mitk::VtkPropRenderer::GetWorldPointPicker() const { return m_WorldPointPicker; } const vtkPointPicker *mitk::VtkPropRenderer::GetPointPicker() const { return m_PointPicker; } const vtkCellPicker *mitk::VtkPropRenderer::GetCellPicker() const { return m_CellPicker; } mitk::VtkPropRenderer::MappersMapType mitk::VtkPropRenderer::GetMappersMap() const { return m_MappersMap; } // Workaround for GL Displaylist bug static int glWorkAroundGlobalCount = 0; bool mitk::VtkPropRenderer::useImmediateModeRendering() { return glWorkAroundGlobalCount > 1; } void mitk::VtkPropRenderer::checkState() { if (m_MapperID == Standard3D) { if (!didCount) { didCount = true; glWorkAroundGlobalCount++; if (glWorkAroundGlobalCount == 2) { MITK_INFO << "Multiple 3D Renderwindows active...: turning Immediate Rendering ON for legacy mappers"; // vtkMapper::GlobalImmediateModeRenderingOn(); } } } else { if (didCount) { didCount = false; glWorkAroundGlobalCount--; if (glWorkAroundGlobalCount == 1) { MITK_INFO << "Single 3D Renderwindow active...: turning Immediate Rendering OFF for legacy mappers"; // vtkMapper::GlobalImmediateModeRenderingOff(); } } } } //### Contains all methods which are neceassry before each VTK Render() call void mitk::VtkPropRenderer::PrepareRender() { if (this->GetMapperID() != m_CameraInitializedForMapperID) { Initialize2DvtkCamera(); // Set parallel projection etc. } GetCameraController()->AdjustCameraToPlane(); } bool mitk::VtkPropRenderer::Initialize2DvtkCamera() { if (this->GetMapperID() == Standard3D) { // activate parallel projection for 2D this->GetVtkRenderer()->GetActiveCamera()->SetParallelProjection(false); vtkSmartPointer style = vtkSmartPointer::New(); this->GetRenderWindow()->GetInteractor()->SetInteractorStyle(style); this->GetRenderWindow()->GetInteractor()->EnableRenderOff(); m_CameraInitializedForMapperID = Standard3D; } else if (this->GetMapperID() == Standard2D) { // activate parallel projection for 2D this->GetVtkRenderer()->GetActiveCamera()->SetParallelProjection(true); // turn the light out in the scene in order to render correct grey values. // TODO Implement a property for light in the 2D render windows (in another method) this->GetVtkRenderer()->RemoveAllLights(); vtkSmartPointer style = vtkSmartPointer::New(); this->GetRenderWindow()->GetInteractor()->SetInteractorStyle(style); this->GetRenderWindow()->GetInteractor()->EnableRenderOff(); m_CameraInitializedForMapperID = Standard2D; } return true; } diff --git a/Modules/QtWidgets/include/QmitkRenderWindow.h b/Modules/QtWidgets/include/QmitkRenderWindow.h index 8f4eb3be61..5727026f9a 100644 --- a/Modules/QtWidgets/include/QmitkRenderWindow.h +++ b/Modules/QtWidgets/include/QmitkRenderWindow.h @@ -1,170 +1,170 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKRENDERWINDOW_H #define QMITKRENDERWINDOW_H #include "mitkRenderWindowBase.h" #include "QmitkRenderWindowMenu.h" #include #include #include #include "mitkBaseRenderer.h" #include "mitkInteractionEventConst.h" class QDragEnterEvent; class QDropEvent; class QInputEvent; /** * \ingroup QmitkModule * \brief MITK implementation of the QVTKWidget */ class MITKQTWIDGETS_EXPORT QmitkRenderWindow : public QVTKOpenGLWidget, public mitk::RenderWindowBase { Q_OBJECT public: QmitkRenderWindow( QWidget *parent = nullptr, const QString &name = "unnamed renderwindow", mitk::VtkPropRenderer *renderer = nullptr, mitk::RenderingManager *renderingManager = nullptr, - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing); + mitk::BaseRenderer::RenderingMode renderingMode = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing); ~QmitkRenderWindow() override; /** * \brief Whether Qt events should be passed to parent (default: true) * * With introduction of the QVTKWidget the behaviour regarding Qt events changed. * QVTKWidget "accepts" Qt events like mouse clicks (i.e. set an "accepted" flag). * When this flag is set, Qt fininshed handling of this event -- otherwise it is * reached through to the widget's parent. * * This reaching through to the parent was implicitly required by QmitkMaterialWidget / QmitkMaterialShowCase. * * The default behaviour of QmitkRenderWindow is now to clear the "accepted" flag * of Qt events after they were handled by QVTKWidget. This way parents can also * handle events. * * If you don't want this behaviour, call SetResendQtEvents(true) on your render window. */ virtual void SetResendQtEvents(bool resend); // Set Layout Index to define the Layout Type void SetLayoutIndex(QmitkRenderWindowMenu::LayoutIndex layoutIndex); // Get Layout Index to define the Layout Type QmitkRenderWindowMenu::LayoutIndex GetLayoutIndex(); // MenuWidget need to update the Layout Design List when Layout had changed void LayoutDesignListChanged(QmitkRenderWindowMenu::LayoutDesign layoutDesign); // Activate or Deactivate MenuWidget. void ActivateMenuWidget(bool state); bool GetActivateMenuWidgetFlag() { return m_MenuWidgetActivated; } // Get it from the QVTKWidget parent vtkRenderWindow *GetVtkRenderWindow() override { return GetRenderWindow(); } vtkRenderWindowInteractor *GetVtkRenderWindowInteractor() override { return nullptr; } protected: // overloaded move handler void moveEvent(QMoveEvent *event) override; // overloaded show handler void showEvent(QShowEvent *event) override; // overloaded mouse press handler void mousePressEvent(QMouseEvent *event) override; // overloaded mouse double-click handler void mouseDoubleClickEvent(QMouseEvent *event) override; // overloaded mouse move handler void mouseMoveEvent(QMouseEvent *event) override; // overloaded mouse release handler void mouseReleaseEvent(QMouseEvent *event) override; // overloaded key press handler void keyPressEvent(QKeyEvent *event) override; // overloaded enter handler void enterEvent(QEvent *) override; // overloaded leave handler void leaveEvent(QEvent *) override; // Overloaded resize handler, see decs in QVTKOpenGLWidget. // Basically, we have to ensure the VTK rendering is updated for each change in window size. void resizeGL(int w, int h) Q_DECL_OVERRIDE; /// \brief Simply says we accept the event type. void dragEnterEvent(QDragEnterEvent *event) override; /// \brief If the dropped type is application/x-mitk-datanodes we process the request by converting to mitk::DataNode /// pointers and emitting the NodesDropped signal. void dropEvent(QDropEvent *event) override; #ifndef QT_NO_WHEELEVENT // overload wheel mouse event void wheelEvent(QWheelEvent *) override; #endif void AdjustRenderWindowMenuVisibility(const QPoint &pos); Q_SIGNALS: void LayoutDesignChanged(QmitkRenderWindowMenu::LayoutDesign); void ResetView(); void CrosshairRotationModeChanged(int); void CrosshairVisibilityChanged(bool); void moved(); /// \brief Emits a signal to say that this window has had the following nodes dropped on it. void NodesDropped(QmitkRenderWindow *thisWindow, std::vector nodes); private Q_SLOTS: void DeferredHideMenu(); private: // Helper Functions to Convert Qt-Events to Mitk-Events mitk::Point2D GetMousePosition(QMouseEvent *me) const; mitk::Point2D GetMousePosition(QWheelEvent *we) const; mitk::InteractionEvent::MouseButtons GetEventButton(QMouseEvent *me) const; mitk::InteractionEvent::MouseButtons GetButtonState(QMouseEvent *me) const; mitk::InteractionEvent::ModifierKeys GetModifiers(QInputEvent *me) const; mitk::InteractionEvent::MouseButtons GetButtonState(QWheelEvent *we) const; std::string GetKeyLetter(QKeyEvent *ke) const; int GetDelta(QWheelEvent *we) const; bool m_ResendQtEvents; QmitkRenderWindowMenu *m_MenuWidget; bool m_MenuWidgetActivated; QmitkRenderWindowMenu::LayoutIndex m_LayoutIndex; vtkSmartPointer m_InternalRenderWindow; }; #endif // QMITKRENDERWINDOW_H diff --git a/Modules/QtWidgets/include/QmitkStdMultiWidget.h b/Modules/QtWidgets/include/QmitkStdMultiWidget.h index 23b7b295ee..50776812cd 100644 --- a/Modules/QtWidgets/include/QmitkStdMultiWidget.h +++ b/Modules/QtWidgets/include/QmitkStdMultiWidget.h @@ -1,165 +1,165 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKSTDMULTIWIDGET_H #define QMITKSTDMULTIWIDGET_H // qt widgets module #include "MitkQtWidgetsExports.h" #include "QmitkAbstractMultiWidget.h" /** * @brief The 'QmitkStdMultiWidget' is a 'QmitkAbstractMultiWidget' that is used to display multiple render windows at once. * Render windows are predefined in a 2x2 design with 3 different 2D view planes and a 3D render window. */ class MITKQTWIDGETS_EXPORT QmitkStdMultiWidget : public QmitkAbstractMultiWidget { Q_OBJECT public: QmitkStdMultiWidget( QWidget *parent = nullptr, Qt::WindowFlags f = nullptr, mitk::RenderingManager *renderingManager = nullptr, - mitk::BaseRenderer::RenderingMode::Type renderingMode = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing, + mitk::BaseRenderer::RenderingMode renderingMode = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing, const QString &name = "stdmulti"); ~QmitkStdMultiWidget() override; virtual void InitializeMultiWidget() override; virtual QmitkRenderWindow* GetRenderWindow(const QString& widgetName) const override; virtual QmitkRenderWindow* GetRenderWindow(const mitk::BaseRenderer::ViewDirection& viewDirection) const override; virtual void SetSelectedPosition(const mitk::Point3D& newPosition, const QString& widgetName) override; virtual const mitk::Point3D GetSelectedPosition(const QString& widgetName) const override; virtual void SetCrosshairVisibility(bool) override; virtual bool GetCrosshairVisibility() const override; virtual void ResetCrosshair() override; virtual void SetWidgetPlaneMode(int mode) override; mitk::SliceNavigationController* GetTimeNavigationController(); void AddPlanesToDataStorage(); void RemovePlanesFromDataStorage(); /** \brief Listener to the CrosshairPositionEvent Ensures the CrosshairPositionEvent is handled only once and at the end of the Qt-Event loop */ void HandleCrosshairPositionEvent(); /** * @brief Convenience method to get a render window widget. * @param Number of the widget (0-3) * @return The render window widget */ QmitkRenderWindow* GetRenderWindow(unsigned int number) const; QmitkRenderWindow* GetRenderWindow1() const; QmitkRenderWindow* GetRenderWindow2() const; QmitkRenderWindow* GetRenderWindow3() const; QmitkRenderWindow* GetRenderWindow4() const; /** * @brief Convenience method to get a widget plane. * @param Number of the widget plane (1-3) * @return The widget plane as data node */ mitk::DataNode::Pointer GetWidgetPlane(unsigned int number) const; mitk::DataNode::Pointer GetWidgetPlane1() const; mitk::DataNode::Pointer GetWidgetPlane2() const; mitk::DataNode::Pointer GetWidgetPlane3() const; /** * @brief SetDecorationColor Set the color of the decoration of the 4 widgets. * * This is used to color the frame of the renderwindow and the corner annatation. * For the first 3 widgets, this color is a property of the helper object nodes * which contain the respective plane geometry. For widget 4, this is a member, * since there is no data node for this widget. */ void SetDecorationColor(unsigned int widgetNumber, mitk::Color color); /** * @brief GetDecorationColorForWidget Get the color for annotation, crosshair and rectangle. * @param widgetNumber Number of the renderwindow (0-3). * @return Color in mitk format. */ mitk::Color GetDecorationColor(unsigned int widgetNumber); public Q_SLOTS: // mouse events virtual void mousePressEvent(QMouseEvent*) override; virtual void moveEvent(QMoveEvent* e) override; virtual void wheelEvent(QWheelEvent* e) override; /// Receives the signal from HandleCrosshairPositionEvent, executes the StatusBar update void HandleCrosshairPositionEventDelayed(); void Fit(); void AddDisplayPlaneSubTree(); void EnsureDisplayContainsPoint(mitk::BaseRenderer *renderer, const mitk::Point3D &p); void SetWidgetPlaneVisibility(const char *widgetName, bool visible, mitk::BaseRenderer *renderer = nullptr); void SetWidgetPlanesVisibility(bool visible, mitk::BaseRenderer *renderer = nullptr); Q_SIGNALS: void WheelMoved(QWheelEvent *); void Moved(); private: virtual void SetLayoutImpl() override; virtual void SynchronizeImpl() override { } virtual void SetInteractionSchemeImpl() override { } void CreateRenderWindowWidgets(); mitk::SliceNavigationController* m_TimeNavigationController; /** * @brief The 3 helper objects which contain the plane geometry. */ mitk::DataNode::Pointer m_PlaneNode1; mitk::DataNode::Pointer m_PlaneNode2; mitk::DataNode::Pointer m_PlaneNode3; /** * @brief m_ParentNodeForGeometryPlanes This helper object is added to the datastorage * and contains the 3 planes for displaying the image geometry (crosshair and 3D planes). */ mitk::DataNode::Pointer m_ParentNodeForGeometryPlanes; /** * @brief m_DecorationColorWidget4 color for annotation and rectangle of widget 4. * * For other widgets1-3, the color is a property of the respective data node. * There is no node for widget 4, hence, we need an extra member. */ mitk::Color m_DecorationColorWidget4; bool m_PendingCrosshairPositionEvent; }; #endif // QMITKSTDMULTIWIDGET_H diff --git a/Modules/QtWidgets/src/QmitkRenderWindow.cpp b/Modules/QtWidgets/src/QmitkRenderWindow.cpp index becf3d7a2c..eaa568ce67 100644 --- a/Modules/QtWidgets/src/QmitkRenderWindow.cpp +++ b/Modules/QtWidgets/src/QmitkRenderWindow.cpp @@ -1,506 +1,506 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkRenderWindow.h" #include "mitkInteractionKeyEvent.h" #include "mitkInternalEvent.h" #include "mitkMouseDoubleClickEvent.h" #include "mitkMouseMoveEvent.h" #include "mitkMousePressEvent.h" #include "mitkMouseReleaseEvent.h" #include "mitkMouseWheelEvent.h" #include #include #include #include #include #include #include #include #include #include #include "QmitkMimeTypes.h" #include "QmitkRenderWindowMenu.h" -QmitkRenderWindow::QmitkRenderWindow(QWidget *parent, const QString &name, mitk::VtkPropRenderer *, mitk::RenderingManager *renderingManager, mitk::BaseRenderer::RenderingMode::Type renderingMode) +QmitkRenderWindow::QmitkRenderWindow(QWidget *parent, const QString &name, mitk::VtkPropRenderer *, mitk::RenderingManager *renderingManager, mitk::BaseRenderer::RenderingMode renderingMode) : QVTKOpenGLWidget(parent) , m_ResendQtEvents(true) , m_MenuWidget(nullptr) , m_MenuWidgetActivated(false) , m_LayoutIndex(QmitkRenderWindowMenu::LayoutIndex::AXIAL) { m_InternalRenderWindow = vtkSmartPointer::New(); m_InternalRenderWindow->SetMultiSamples(0); m_InternalRenderWindow->SetAlphaBitPlanes(0); SetRenderWindow(m_InternalRenderWindow); Initialize(renderingManager, name.toStdString().c_str(), renderingMode); setFocusPolicy(Qt::StrongFocus); setMouseTracking(true); QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); setSizePolicy(sizePolicy); } QmitkRenderWindow::~QmitkRenderWindow() { Destroy(); // Destroy mitkRenderWindowBase } void QmitkRenderWindow::SetResendQtEvents(bool resend) { m_ResendQtEvents = resend; } void QmitkRenderWindow::SetLayoutIndex(QmitkRenderWindowMenu::LayoutIndex layoutIndex) { m_LayoutIndex = layoutIndex; if (nullptr != m_MenuWidget) { m_MenuWidget->SetLayoutIndex(layoutIndex); } } QmitkRenderWindowMenu::LayoutIndex QmitkRenderWindow::GetLayoutIndex() { if (nullptr != m_MenuWidget) { return m_MenuWidget->GetLayoutIndex(); } else { return QmitkRenderWindowMenu::LayoutIndex::AXIAL; } } void QmitkRenderWindow::LayoutDesignListChanged(QmitkRenderWindowMenu::LayoutDesign layoutDesign) { if (nullptr != m_MenuWidget) { m_MenuWidget->UpdateLayoutDesignList(layoutDesign); } } void QmitkRenderWindow::ActivateMenuWidget(bool state) { if (nullptr == m_MenuWidget) { m_MenuWidget = new QmitkRenderWindowMenu(this, nullptr, m_Renderer); m_MenuWidget->SetLayoutIndex(m_LayoutIndex); } m_MenuWidgetActivated = state; if (m_MenuWidgetActivated) { connect(m_MenuWidget, &QmitkRenderWindowMenu::LayoutDesignChanged, this, &QmitkRenderWindow::LayoutDesignChanged); connect(m_MenuWidget, &QmitkRenderWindowMenu::ResetView, this, &QmitkRenderWindow::ResetView); connect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairVisibilityChanged, this, &QmitkRenderWindow::CrosshairVisibilityChanged); connect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairRotationModeChanged, this, &QmitkRenderWindow::CrosshairRotationModeChanged); } else { disconnect(m_MenuWidget, &QmitkRenderWindowMenu::LayoutDesignChanged, this, &QmitkRenderWindow::LayoutDesignChanged); disconnect(m_MenuWidget, &QmitkRenderWindowMenu::ResetView, this, &QmitkRenderWindow::ResetView); disconnect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairVisibilityChanged, this, &QmitkRenderWindow::CrosshairVisibilityChanged); disconnect(m_MenuWidget, &QmitkRenderWindowMenu::CrosshairRotationModeChanged, this, &QmitkRenderWindow::CrosshairRotationModeChanged); m_MenuWidget->hide(); } } void QmitkRenderWindow::moveEvent(QMoveEvent *event) { QVTKOpenGLWidget::moveEvent(event); // after a move the overlays need to be positioned emit moved(); } void QmitkRenderWindow::showEvent(QShowEvent *event) { QVTKOpenGLWidget::showEvent(event); // this singleshot is necessary to have the overlays positioned correctly after initial show // simple call of moved() is no use here!! QTimer::singleShot(0, this, SIGNAL(moved())); } void QmitkRenderWindow::mousePressEvent(QMouseEvent *me) { // Get mouse position in vtk display coordinate system. me contains qt display infos... mitk::Point2D displayPos = GetMousePosition(me); mitk::MousePressEvent::Pointer mPressEvent = mitk::MousePressEvent::New(m_Renderer, displayPos, GetButtonState(me), GetModifiers(me), GetEventButton(me)); if (!this->HandleEvent(mPressEvent.GetPointer())) { QVTKOpenGLWidget::mousePressEvent(me); } if (m_ResendQtEvents) { me->ignore(); } } void QmitkRenderWindow::mouseDoubleClickEvent(QMouseEvent *me) { mitk::Point2D displayPos = GetMousePosition(me); mitk::MouseDoubleClickEvent::Pointer mPressEvent = mitk::MouseDoubleClickEvent::New(m_Renderer, displayPos, GetButtonState(me), GetModifiers(me), GetEventButton(me)); if (!this->HandleEvent(mPressEvent.GetPointer())) { QVTKOpenGLWidget::mousePressEvent(me); } if (m_ResendQtEvents) { me->ignore(); } } void QmitkRenderWindow::mouseReleaseEvent(QMouseEvent *me) { mitk::Point2D displayPos = GetMousePosition(me); mitk::MouseReleaseEvent::Pointer mReleaseEvent = mitk::MouseReleaseEvent::New(m_Renderer, displayPos, GetButtonState(me), GetModifiers(me), GetEventButton(me)); if (!this->HandleEvent(mReleaseEvent.GetPointer())) { QVTKOpenGLWidget::mouseReleaseEvent(me); } if (m_ResendQtEvents) { me->ignore(); } } void QmitkRenderWindow::mouseMoveEvent(QMouseEvent *me) { mitk::Point2D displayPos = GetMousePosition(me); AdjustRenderWindowMenuVisibility(me->pos()); mitk::MouseMoveEvent::Pointer mMoveEvent = mitk::MouseMoveEvent::New(m_Renderer, displayPos, GetButtonState(me), GetModifiers(me)); if (!this->HandleEvent(mMoveEvent.GetPointer())) { QVTKOpenGLWidget::mouseMoveEvent(me); } } void QmitkRenderWindow::wheelEvent(QWheelEvent *we) { mitk::Point2D displayPos = GetMousePosition(we); mitk::MouseWheelEvent::Pointer mWheelEvent = mitk::MouseWheelEvent::New(m_Renderer, displayPos, GetButtonState(we), GetModifiers(we), GetDelta(we)); if (!this->HandleEvent(mWheelEvent.GetPointer())) { QVTKOpenGLWidget::wheelEvent(we); } if (m_ResendQtEvents) { we->ignore(); } } void QmitkRenderWindow::keyPressEvent(QKeyEvent *ke) { mitk::InteractionEvent::ModifierKeys modifiers = GetModifiers(ke); std::string key = GetKeyLetter(ke); mitk::InteractionKeyEvent::Pointer keyEvent = mitk::InteractionKeyEvent::New(m_Renderer, key, modifiers); if (!this->HandleEvent(keyEvent.GetPointer())) { QVTKOpenGLWidget::keyPressEvent(ke); } if (m_ResendQtEvents) { ke->ignore(); } } void QmitkRenderWindow::enterEvent(QEvent *e) { // TODO implement new event QVTKOpenGLWidget::enterEvent(e); } void QmitkRenderWindow::leaveEvent(QEvent *e) { mitk::InternalEvent::Pointer internalEvent = mitk::InternalEvent::New(this->m_Renderer, nullptr, "LeaveRenderWindow"); this->HandleEvent(internalEvent.GetPointer()); if (nullptr != m_MenuWidget) { m_MenuWidget->smoothHide(); } QVTKOpenGLWidget::leaveEvent(e); } void QmitkRenderWindow::resizeGL(int w, int h) { this->GetRenderer()->GetRenderingManager()->ForceImmediateUpdate(GetRenderWindow()); QVTKOpenGLWidget::resizeGL(w, h); } void QmitkRenderWindow::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasFormat("application/x-mitk-datanodes")) { event->accept(); } } void QmitkRenderWindow::dropEvent(QDropEvent *event) { QList dataNodeList = QmitkMimeTypes::ToDataNodePtrList(event->mimeData()); if (!dataNodeList.empty()) { emit NodesDropped(this, dataNodeList.toVector().toStdVector()); } } void QmitkRenderWindow::AdjustRenderWindowMenuVisibility(const QPoint & /*pos*/) { if (nullptr != m_MenuWidget) { m_MenuWidget->ShowMenu(); m_MenuWidget->MoveWidgetToCorrectPos(1.0f); } } void QmitkRenderWindow::DeferredHideMenu() { MITK_DEBUG << "QmitkRenderWindow::DeferredHideMenu"; if (nullptr != m_MenuWidget) { m_MenuWidget->HideMenu(); } } mitk::Point2D QmitkRenderWindow::GetMousePosition(QMouseEvent *me) const { mitk::Point2D point; point[0] = me->x(); // We need to convert the y component, as the display and vtk have other definitions for the y direction point[1] = m_Renderer->GetSizeY() - me->y(); return point; } mitk::Point2D QmitkRenderWindow::GetMousePosition(QWheelEvent *we) const { mitk::Point2D point; point[0] = we->x(); // We need to convert the y component, as the display and vtk have other definitions for the y direction point[1] = m_Renderer->GetSizeY() - we->y(); return point; } mitk::InteractionEvent::MouseButtons QmitkRenderWindow::GetEventButton(QMouseEvent *me) const { mitk::InteractionEvent::MouseButtons eventButton; switch (me->button()) { case Qt::LeftButton: eventButton = mitk::InteractionEvent::LeftMouseButton; break; case Qt::RightButton: eventButton = mitk::InteractionEvent::RightMouseButton; break; case Qt::MidButton: eventButton = mitk::InteractionEvent::MiddleMouseButton; break; default: eventButton = mitk::InteractionEvent::NoButton; break; } return eventButton; } mitk::InteractionEvent::MouseButtons QmitkRenderWindow::GetButtonState(QMouseEvent *me) const { mitk::InteractionEvent::MouseButtons buttonState = mitk::InteractionEvent::NoButton; if (me->buttons() & Qt::LeftButton) { buttonState = buttonState | mitk::InteractionEvent::LeftMouseButton; } if (me->buttons() & Qt::RightButton) { buttonState = buttonState | mitk::InteractionEvent::RightMouseButton; } if (me->buttons() & Qt::MidButton) { buttonState = buttonState | mitk::InteractionEvent::MiddleMouseButton; } return buttonState; } mitk::InteractionEvent::ModifierKeys QmitkRenderWindow::GetModifiers(QInputEvent *me) const { mitk::InteractionEvent::ModifierKeys modifiers = mitk::InteractionEvent::NoKey; if (me->modifiers() & Qt::ALT) { modifiers = modifiers | mitk::InteractionEvent::AltKey; } if (me->modifiers() & Qt::CTRL) { modifiers = modifiers | mitk::InteractionEvent::ControlKey; } if (me->modifiers() & Qt::SHIFT) { modifiers = modifiers | mitk::InteractionEvent::ShiftKey; } return modifiers; } mitk::InteractionEvent::MouseButtons QmitkRenderWindow::GetButtonState(QWheelEvent *we) const { mitk::InteractionEvent::MouseButtons buttonState = mitk::InteractionEvent::NoButton; if (we->buttons() & Qt::LeftButton) { buttonState = buttonState | mitk::InteractionEvent::LeftMouseButton; } if (we->buttons() & Qt::RightButton) { buttonState = buttonState | mitk::InteractionEvent::RightMouseButton; } if (we->buttons() & Qt::MidButton) { buttonState = buttonState | mitk::InteractionEvent::MiddleMouseButton; } return buttonState; } std::string QmitkRenderWindow::GetKeyLetter(QKeyEvent *ke) const { // Converting Qt Key Event to string element. std::string key = ""; int tkey = ke->key(); if (tkey < 128) { // standard ascii letter key = (char)toupper(tkey); } else { // special keys switch (tkey) { case Qt::Key_Return: key = mitk::InteractionEvent::KeyReturn; break; case Qt::Key_Enter: key = mitk::InteractionEvent::KeyEnter; break; case Qt::Key_Escape: key = mitk::InteractionEvent::KeyEsc; break; case Qt::Key_Delete: key = mitk::InteractionEvent::KeyDelete; break; case Qt::Key_Up: key = mitk::InteractionEvent::KeyArrowUp; break; case Qt::Key_Down: key = mitk::InteractionEvent::KeyArrowDown; break; case Qt::Key_Left: key = mitk::InteractionEvent::KeyArrowLeft; break; case Qt::Key_Right: key = mitk::InteractionEvent::KeyArrowRight; break; case Qt::Key_F1: key = mitk::InteractionEvent::KeyF1; break; case Qt::Key_F2: key = mitk::InteractionEvent::KeyF2; break; case Qt::Key_F3: key = mitk::InteractionEvent::KeyF3; break; case Qt::Key_F4: key = mitk::InteractionEvent::KeyF4; break; case Qt::Key_F5: key = mitk::InteractionEvent::KeyF5; break; case Qt::Key_F6: key = mitk::InteractionEvent::KeyF6; break; case Qt::Key_F7: key = mitk::InteractionEvent::KeyF7; break; case Qt::Key_F8: key = mitk::InteractionEvent::KeyF8; break; case Qt::Key_F9: key = mitk::InteractionEvent::KeyF9; break; case Qt::Key_F10: key = mitk::InteractionEvent::KeyF10; break; case Qt::Key_F11: key = mitk::InteractionEvent::KeyF11; break; case Qt::Key_F12: key = mitk::InteractionEvent::KeyF12; break; case Qt::Key_End: key = mitk::InteractionEvent::KeyEnd; break; case Qt::Key_Home: key = mitk::InteractionEvent::KeyPos1; break; case Qt::Key_Insert: key = mitk::InteractionEvent::KeyInsert; break; case Qt::Key_PageDown: key = mitk::InteractionEvent::KeyPageDown; break; case Qt::Key_PageUp: key = mitk::InteractionEvent::KeyPageUp; break; case Qt::Key_Space: key = mitk::InteractionEvent::KeySpace; break; } } return key; } int QmitkRenderWindow::GetDelta(QWheelEvent *we) const { return we->delta(); } diff --git a/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp b/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp index 01291db031..7ec5518a21 100644 --- a/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp +++ b/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp @@ -1,808 +1,808 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #define SMW_INFO MITK_INFO("widget.stdmulti") #include "QmitkStdMultiWidget.h" #include "QmitkRenderWindowWidget.h" // mitk core #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // qt #include #include #include // vtk #include // c++ #include QmitkStdMultiWidget::QmitkStdMultiWidget(QWidget *parent, Qt::WindowFlags f/* = 0*/, mitk::RenderingManager *renderingManager/* = nullptr*/, - mitk::BaseRenderer::RenderingMode::Type renderingMode/* = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing*/, + mitk::BaseRenderer::RenderingMode renderingMode/* = mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing*/, const QString &name/* = "stdmulti"*/) : QmitkAbstractMultiWidget(parent, f, renderingManager, renderingMode, name) , m_TimeNavigationController(nullptr) , m_PendingCrosshairPositionEvent(false) { m_TimeNavigationController = GetRenderingManager()->GetTimeNavigationController(); } QmitkStdMultiWidget::~QmitkStdMultiWidget() { m_TimeNavigationController->Disconnect(GetRenderWindow1()->GetSliceNavigationController()); m_TimeNavigationController->Disconnect(GetRenderWindow2()->GetSliceNavigationController()); m_TimeNavigationController->Disconnect(GetRenderWindow3()->GetSliceNavigationController()); m_TimeNavigationController->Disconnect(GetRenderWindow4()->GetSliceNavigationController()); } void QmitkStdMultiWidget::InitializeMultiWidget() { // yellow is default color for widget4 m_DecorationColorWidget4[0] = 1.0f; m_DecorationColorWidget4[1] = 1.0f; m_DecorationColorWidget4[2] = 0.0f; SetLayout(2, 2); // transfer colors in WorldGeometry-Nodes of the associated Renderer mitk::IntProperty::Pointer layer; // of widget 1 m_PlaneNode1 = mitk::BaseRenderer::GetInstance(GetRenderWindow1()->GetRenderWindow())->GetCurrentWorldPlaneGeometryNode(); m_PlaneNode1->SetColor(GetDecorationColor(0)); layer = mitk::IntProperty::New(1000); m_PlaneNode1->SetProperty("layer", layer); // of widget 2 m_PlaneNode2 = mitk::BaseRenderer::GetInstance(GetRenderWindow2()->GetRenderWindow())->GetCurrentWorldPlaneGeometryNode(); m_PlaneNode2->SetColor(GetDecorationColor(1)); layer = mitk::IntProperty::New(1000); m_PlaneNode2->SetProperty("layer", layer); // of widget 3 m_PlaneNode3 = mitk::BaseRenderer::GetInstance(GetRenderWindow3()->GetRenderWindow())->GetCurrentWorldPlaneGeometryNode(); m_PlaneNode3->SetColor(GetDecorationColor(2)); layer = mitk::IntProperty::New(1000); m_PlaneNode3->SetProperty("layer", layer); // the parent node m_ParentNodeForGeometryPlanes = mitk::BaseRenderer::GetInstance(GetRenderWindow4()->GetRenderWindow())->GetCurrentWorldPlaneGeometryNode(); layer = mitk::IntProperty::New(1000); m_ParentNodeForGeometryPlanes->SetProperty("layer", layer); AddDisplayPlaneSubTree(); } QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow(const QString& widgetName) const { if ("axial" == widgetName) { return GetRenderWindow1(); } if ("sagittal" == widgetName) { return GetRenderWindow2(); } if ("coronal" == widgetName) { return GetRenderWindow3(); } if ("3d" == widgetName) { return GetRenderWindow4(); } return QmitkAbstractMultiWidget::GetRenderWindow(widgetName); } QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow(const mitk::BaseRenderer::ViewDirection& viewDirection) const { return GetRenderWindow(static_cast(viewDirection)); } void QmitkStdMultiWidget::SetSelectedPosition(const mitk::Point3D& newPosition, const QString& /*widgetName*/) { GetRenderWindow1()->GetSliceNavigationController()->SelectSliceByPoint(newPosition); GetRenderWindow2()->GetSliceNavigationController()->SelectSliceByPoint(newPosition); GetRenderWindow3()->GetSliceNavigationController()->SelectSliceByPoint(newPosition); RequestUpdateAll(); } const mitk::Point3D QmitkStdMultiWidget::GetSelectedPosition(const QString& /*widgetName*/) const { const mitk::PlaneGeometry* plane1 = GetRenderWindow1()->GetSliceNavigationController()->GetCurrentPlaneGeometry(); const mitk::PlaneGeometry* plane2 = GetRenderWindow2()->GetSliceNavigationController()->GetCurrentPlaneGeometry(); const mitk::PlaneGeometry* plane3 = GetRenderWindow3()->GetSliceNavigationController()->GetCurrentPlaneGeometry(); mitk::Line3D line; if ((plane1 != nullptr) && (plane2 != nullptr) && (plane1->IntersectionLine(plane2, line))) { mitk::Point3D point; if ((plane3 != nullptr) && (plane3->IntersectionPoint(line, point))) { return point; } } return mitk::Point3D(); } void QmitkStdMultiWidget::SetCrosshairVisibility(bool visible) { if (m_PlaneNode1.IsNotNull()) { m_PlaneNode1->SetVisibility(visible); } if (m_PlaneNode2.IsNotNull()) { m_PlaneNode2->SetVisibility(visible); } if (m_PlaneNode3.IsNotNull()) { m_PlaneNode3->SetVisibility(visible); } RequestUpdateAll(); } bool QmitkStdMultiWidget::GetCrosshairVisibility() const { bool crosshairVisibility = true; if (m_PlaneNode1.IsNotNull()) { bool visibilityProperty = false; m_PlaneNode1->GetVisibility(visibilityProperty, nullptr); crosshairVisibility &= visibilityProperty; } if (m_PlaneNode2.IsNotNull()) { bool visibilityProperty = false; crosshairVisibility &= m_PlaneNode2->GetVisibility(visibilityProperty, nullptr); crosshairVisibility &= visibilityProperty; } if (m_PlaneNode3.IsNotNull()) { bool visibilityProperty = false; crosshairVisibility &= m_PlaneNode3->GetVisibility(visibilityProperty, nullptr); crosshairVisibility &= visibilityProperty; } return crosshairVisibility; } void QmitkStdMultiWidget::ResetCrosshair() { auto dataStorage = GetDataStorage(); if (nullptr == dataStorage) { return; } GetRenderingManager()->InitializeViewsByBoundingObjects(dataStorage); SetWidgetPlaneMode(mitk::InteractionSchemeSwitcher::MITKStandard); } void QmitkStdMultiWidget::SetWidgetPlaneMode(int userMode) { MITK_DEBUG << "Changing crosshair mode to " << userMode; switch (userMode) { case 0: SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKStandard); break; case 1: SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKRotationUncoupled); break; case 2: SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKRotationCoupled); break; case 3: SetInteractionScheme(mitk::InteractionSchemeSwitcher::MITKSwivel); break; } } mitk::SliceNavigationController* QmitkStdMultiWidget::GetTimeNavigationController() { return m_TimeNavigationController; } void QmitkStdMultiWidget::AddPlanesToDataStorage() { auto dataStorage = GetDataStorage(); if (nullptr == dataStorage) { return; } if (m_PlaneNode1.IsNotNull() && m_PlaneNode2.IsNotNull() && m_PlaneNode3.IsNotNull() && m_ParentNodeForGeometryPlanes.IsNotNull()) { dataStorage->Add(m_ParentNodeForGeometryPlanes); dataStorage->Add(m_PlaneNode1, m_ParentNodeForGeometryPlanes); dataStorage->Add(m_PlaneNode2, m_ParentNodeForGeometryPlanes); dataStorage->Add(m_PlaneNode3, m_ParentNodeForGeometryPlanes); } } void QmitkStdMultiWidget::RemovePlanesFromDataStorage() { auto dataStorage = GetDataStorage(); if (nullptr == dataStorage) { return; } if (m_PlaneNode1.IsNotNull() && m_PlaneNode2.IsNotNull() && m_PlaneNode3.IsNotNull() && m_ParentNodeForGeometryPlanes.IsNotNull()) { dataStorage->Remove(m_PlaneNode1); dataStorage->Remove(m_PlaneNode2); dataStorage->Remove(m_PlaneNode3); dataStorage->Remove(m_ParentNodeForGeometryPlanes); } } void QmitkStdMultiWidget::HandleCrosshairPositionEvent() { if (!m_PendingCrosshairPositionEvent) { m_PendingCrosshairPositionEvent = true; QTimer::singleShot(0, this, SLOT(HandleCrosshairPositionEventDelayed())); } } QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow(unsigned int number) const { switch (number) { case 0: return GetRenderWindow1(); case 1: return GetRenderWindow2(); case 2: return GetRenderWindow3(); case 3: return GetRenderWindow4(); default: MITK_ERROR << "Requested unknown render window"; break; } return nullptr; } QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow1() const { return QmitkAbstractMultiWidget::GetRenderWindow(GetNameFromIndex(0, 0)); } QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow2() const { return QmitkAbstractMultiWidget::GetRenderWindow(GetNameFromIndex(0, 1)); } QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow3() const { return QmitkAbstractMultiWidget::GetRenderWindow(GetNameFromIndex(1, 0)); } QmitkRenderWindow* QmitkStdMultiWidget::GetRenderWindow4() const { return QmitkAbstractMultiWidget::GetRenderWindow(GetNameFromIndex(1, 1)); } mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane1() const { return m_PlaneNode1; } mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane2() const { return m_PlaneNode2; } mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane3() const { return m_PlaneNode3; } mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane(unsigned number) const { switch (number) { case 1: return m_PlaneNode1; case 2: return m_PlaneNode2; case 3: return m_PlaneNode3; default: MITK_ERROR << "Requested unknown render window"; break; } return nullptr; } void QmitkStdMultiWidget::SetDecorationColor(unsigned int widgetNumber, mitk::Color color) { switch (widgetNumber) { case 0: if (m_PlaneNode1.IsNotNull()) { m_PlaneNode1->SetColor(color); } break; case 1: if (m_PlaneNode2.IsNotNull()) { m_PlaneNode2->SetColor(color); } break; case 2: if (m_PlaneNode3.IsNotNull()) { m_PlaneNode3->SetColor(color); } break; case 3: m_DecorationColorWidget4 = color; break; default: MITK_ERROR << "Decoration color for unknown widget!"; break; } } mitk::Color QmitkStdMultiWidget::GetDecorationColor(unsigned int widgetNumber) { // The implementation looks a bit messy here, but it avoids // synchronization of the color of the geometry nodes and an // internal member here. // Default colors were chosen for decent visibility. // Feel free to change your preferences in the workbench. float tmp[3] = { 0.0f, 0.0f, 0.0f }; switch (widgetNumber) { case 0: { if (m_PlaneNode1.IsNotNull()) { if (m_PlaneNode1->GetColor(tmp)) { return dynamic_cast(m_PlaneNode1->GetProperty("color"))->GetColor(); } } float red[3] = { 0.753f, 0.0f, 0.0f }; // This is #C00000 in hex return mitk::Color(red); } case 1: { if (m_PlaneNode2.IsNotNull()) { if (m_PlaneNode2->GetColor(tmp)) { return dynamic_cast(m_PlaneNode2->GetProperty("color"))->GetColor(); } } float green[3] = { 0.0f, 0.69f, 0.0f }; // This is #00B000 in hex return mitk::Color(green); } case 2: { if (m_PlaneNode3.IsNotNull()) { if (m_PlaneNode3->GetColor(tmp)) { return dynamic_cast(m_PlaneNode3->GetProperty("color"))->GetColor(); } } float blue[3] = { 0.0, 0.502f, 1.0f }; // This is #0080FF in hex return mitk::Color(blue); } case 3: { return m_DecorationColorWidget4; } default: MITK_ERROR << "Decoration color for unknown widget!"; float black[3] = { 0.0f, 0.0f, 0.0f }; return mitk::Color(black); } } void QmitkStdMultiWidget::mousePressEvent(QMouseEvent* e) { if (QEvent::MouseButtonPress != e->type()) { return; } auto renderWindowWidget = dynamic_cast(this->sender()); if (nullptr == renderWindowWidget) { return; } auto renderWindowWidgetPointer = GetRenderWindowWidget(renderWindowWidget->GetWidgetName()); SetActiveRenderWindowWidget(renderWindowWidgetPointer); } void QmitkStdMultiWidget::moveEvent(QMoveEvent* e) { QWidget::moveEvent(e); // it is necessary to readjust the position of the Annotation as the StdMultiWidget has moved // unfortunately it's not done by QmitkRenderWindow::moveEvent -> must be done here emit Moved(); } void QmitkStdMultiWidget::wheelEvent(QWheelEvent* e) { emit WheelMoved(e); } void QmitkStdMultiWidget::HandleCrosshairPositionEventDelayed() { auto dataStorage = GetDataStorage(); if (nullptr == dataStorage) { return; } m_PendingCrosshairPositionEvent = false; // find image with highest layer mitk::TNodePredicateDataType::Pointer isImageData = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer nodes = dataStorage->GetSubset(isImageData).GetPointer(); mitk::Point3D crosshairPos = GetSelectedPosition(""); mitk::BaseRenderer* baseRenderer = GetRenderWindow1()->GetSliceNavigationController()->GetRenderer(); auto globalCurrentTimePoint = baseRenderer->GetTime(); mitk::DataNode::Pointer node = mitk::FindTopmostVisibleNode(nodes, crosshairPos, globalCurrentTimePoint, baseRenderer); mitk::DataNode::Pointer topSourceNode; mitk::Image::Pointer image; bool isBinary = false; int component = 0; if (node.IsNotNull()) { node->GetBoolProperty("binary", isBinary); if (isBinary) { mitk::DataStorage::SetOfObjects::ConstPointer sourcenodes = dataStorage->GetSources(node, nullptr, true); if (!sourcenodes->empty()) { topSourceNode = mitk::FindTopmostVisibleNode(sourcenodes, crosshairPos, globalCurrentTimePoint, baseRenderer); } if (topSourceNode.IsNotNull()) { image = dynamic_cast(topSourceNode->GetData()); topSourceNode->GetIntProperty("Image.Displayed Component", component); } else { image = dynamic_cast(node->GetData()); node->GetIntProperty("Image.Displayed Component", component); } } else { image = dynamic_cast(node->GetData()); node->GetIntProperty("Image.Displayed Component", component); } } std::string statusText; std::stringstream stream; itk::Index<3> p; unsigned int timestep = baseRenderer->GetTimeStep(); if (image.IsNotNull() && (image->GetTimeSteps() > timestep)) { image->GetGeometry()->WorldToIndex(crosshairPos, p); stream.precision(2); stream << "Position: <" << std::fixed << crosshairPos[0] << ", " << std::fixed << crosshairPos[1] << ", " << std::fixed << crosshairPos[2] << "> mm"; stream << "; Index: <" << p[0] << ", " << p[1] << ", " << p[2] << "> "; mitk::ScalarType pixelValue; mitkPixelTypeMultiplex5(mitk::FastSinglePixelAccess, image->GetChannelDescriptor().GetPixelType(), image, image->GetVolumeData(image->GetTimeGeometry()->TimePointToTimeStep(globalCurrentTimePoint)), p, pixelValue, component); if (fabs(pixelValue) > 1000000 || fabs(pixelValue) < 0.01) { stream << "; Time: " << globalCurrentTimePoint << " ms; Pixelvalue: " << std::scientific << pixelValue << " "; } else { stream << "; Time: " << globalCurrentTimePoint << " ms; Pixelvalue: " << pixelValue << " "; } } else { stream << "No image information at this position!"; } statusText = stream.str(); mitk::StatusBar::GetInstance()->DisplayGreyValueText(statusText.c_str()); } void QmitkStdMultiWidget::Fit() { vtkSmartPointer vtkrenderer; vtkrenderer = mitk::BaseRenderer::GetInstance(GetRenderWindow1()->GetRenderWindow())->GetVtkRenderer(); if (nullptr != vtkrenderer) { vtkrenderer->ResetCamera(); } vtkrenderer = mitk::BaseRenderer::GetInstance(GetRenderWindow2()->GetRenderWindow())->GetVtkRenderer(); if (nullptr != vtkrenderer) { vtkrenderer->ResetCamera(); } vtkrenderer = mitk::BaseRenderer::GetInstance(GetRenderWindow3()->GetRenderWindow())->GetVtkRenderer(); if (nullptr != vtkrenderer) { vtkrenderer->ResetCamera(); } vtkrenderer = mitk::BaseRenderer::GetInstance(GetRenderWindow4()->GetRenderWindow())->GetVtkRenderer(); if (nullptr != vtkrenderer) { vtkrenderer->ResetCamera(); } mitk::BaseRenderer::GetInstance(GetRenderWindow1()->GetRenderWindow())->GetCameraController()->Fit(); mitk::BaseRenderer::GetInstance(GetRenderWindow2()->GetRenderWindow())->GetCameraController()->Fit(); mitk::BaseRenderer::GetInstance(GetRenderWindow3()->GetRenderWindow())->GetCameraController()->Fit(); mitk::BaseRenderer::GetInstance(GetRenderWindow4()->GetRenderWindow())->GetCameraController()->Fit(); int w = vtkObject::GetGlobalWarningDisplay(); vtkObject::GlobalWarningDisplayOff(); vtkObject::SetGlobalWarningDisplay(w); } void QmitkStdMultiWidget::AddDisplayPlaneSubTree() { // add the displayed planes of the multiwidget to a node to which the subtree // @a planesSubTree points ... mitk::PlaneGeometryDataMapper2D::Pointer mapper; // ... of widget 1 mitk::BaseRenderer* renderer1 = mitk::BaseRenderer::GetInstance(GetRenderWindow1()->GetRenderWindow()); m_PlaneNode1 = renderer1->GetCurrentWorldPlaneGeometryNode(); m_PlaneNode1->SetProperty("visible", mitk::BoolProperty::New(true)); m_PlaneNode1->SetProperty("name", mitk::StringProperty::New(std::string(renderer1->GetName()) + ".plane")); m_PlaneNode1->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); m_PlaneNode1->SetProperty("helper object", mitk::BoolProperty::New(true)); mapper = mitk::PlaneGeometryDataMapper2D::New(); m_PlaneNode1->SetMapper(mitk::BaseRenderer::Standard2D, mapper); // ... of widget 2 mitk::BaseRenderer* renderer2 = mitk::BaseRenderer::GetInstance(GetRenderWindow2()->GetRenderWindow()); m_PlaneNode2 = renderer2->GetCurrentWorldPlaneGeometryNode(); m_PlaneNode2->SetProperty("visible", mitk::BoolProperty::New(true)); m_PlaneNode2->SetProperty("name", mitk::StringProperty::New(std::string(renderer2->GetName()) + ".plane")); m_PlaneNode2->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); m_PlaneNode2->SetProperty("helper object", mitk::BoolProperty::New(true)); mapper = mitk::PlaneGeometryDataMapper2D::New(); m_PlaneNode2->SetMapper(mitk::BaseRenderer::Standard2D, mapper); // ... of widget 3 mitk::BaseRenderer *renderer3 = mitk::BaseRenderer::GetInstance(GetRenderWindow3()->GetRenderWindow()); m_PlaneNode3 = renderer3->GetCurrentWorldPlaneGeometryNode(); m_PlaneNode3->SetProperty("visible", mitk::BoolProperty::New(true)); m_PlaneNode3->SetProperty("name", mitk::StringProperty::New(std::string(renderer3->GetName()) + ".plane")); m_PlaneNode3->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); m_PlaneNode3->SetProperty("helper object", mitk::BoolProperty::New(true)); mapper = mitk::PlaneGeometryDataMapper2D::New(); m_PlaneNode3->SetMapper(mitk::BaseRenderer::Standard2D, mapper); m_ParentNodeForGeometryPlanes = mitk::DataNode::New(); m_ParentNodeForGeometryPlanes->SetProperty("name", mitk::StringProperty::New("Widgets")); m_ParentNodeForGeometryPlanes->SetProperty("helper object", mitk::BoolProperty::New(true)); } void QmitkStdMultiWidget::EnsureDisplayContainsPoint(mitk::BaseRenderer *renderer, const mitk::Point3D &p) { mitk::Point2D pointOnDisplay; renderer->WorldToDisplay(p, pointOnDisplay); if (pointOnDisplay[0] < renderer->GetVtkRenderer()->GetOrigin()[0] || pointOnDisplay[1] < renderer->GetVtkRenderer()->GetOrigin()[1] || pointOnDisplay[0] > renderer->GetVtkRenderer()->GetOrigin()[0] + renderer->GetViewportSize()[0] || pointOnDisplay[1] > renderer->GetVtkRenderer()->GetOrigin()[1] + renderer->GetViewportSize()[1]) { mitk::Point2D pointOnPlane; renderer->GetCurrentWorldPlaneGeometry()->Map(p, pointOnPlane); renderer->GetCameraController()->MoveCameraToPoint(pointOnPlane); } } void QmitkStdMultiWidget::SetWidgetPlaneVisibility(const char *widgetName, bool visible, mitk::BaseRenderer *renderer) { auto dataStorage = GetDataStorage(); if (nullptr != dataStorage) { mitk::DataNode* dataNode = dataStorage->GetNamedNode(widgetName); if (dataNode != nullptr) { dataNode->SetVisibility(visible, renderer); } } } void QmitkStdMultiWidget::SetWidgetPlanesVisibility(bool visible, mitk::BaseRenderer *renderer) { if (m_PlaneNode1.IsNotNull()) { m_PlaneNode1->SetVisibility(visible, renderer); } if (m_PlaneNode2.IsNotNull()) { m_PlaneNode2->SetVisibility(visible, renderer); } if (m_PlaneNode3.IsNotNull()) { m_PlaneNode3->SetVisibility(visible, renderer); } GetRenderingManager()->RequestUpdateAll(); } ////////////////////////////////////////////////////////////////////////// // PRIVATE ////////////////////////////////////////////////////////////////////////// void QmitkStdMultiWidget::SetLayoutImpl() { CreateRenderWindowWidgets(); GetMultiWidgetLayoutManager()->SetLayoutDesign(QmitkMultiWidgetLayoutManager::LayoutDesign::DEFAULT); // Initialize views as axial, sagittal, coronal to all data objects in DataStorage auto geo = GetDataStorage()->ComputeBoundingGeometry3D(GetDataStorage()->GetAll()); GetRenderingManager()->InitializeViews(geo); } void QmitkStdMultiWidget::CreateRenderWindowWidgets() { // create axial render window (widget) QString renderWindowWidgetName = GetNameFromIndex(0, 0); RenderWindowWidgetPointer renderWindowWidget1 = std::make_shared(this, renderWindowWidgetName, GetDataStorage(), GetRenderingManager()); auto renderWindow1 = renderWindowWidget1->GetRenderWindow(); renderWindow1->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); renderWindowWidget1->SetDecorationColor(GetDecorationColor(0)); renderWindowWidget1->SetCornerAnnotationText("Axial"); renderWindowWidget1->GetRenderWindow()->SetLayoutIndex(ViewDirection::AXIAL); AddRenderWindowWidget(renderWindowWidgetName, renderWindowWidget1); // create sagittal render window (widget) renderWindowWidgetName = GetNameFromIndex(0, 1); RenderWindowWidgetPointer renderWindowWidget2 = std::make_shared(this, renderWindowWidgetName, GetDataStorage(), GetRenderingManager()); auto renderWindow2 = renderWindowWidget2->GetRenderWindow(); renderWindow2->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Sagittal); renderWindowWidget2->SetDecorationColor(GetDecorationColor(1)); renderWindowWidget2->setStyleSheet("border: 0px"); renderWindowWidget2->SetCornerAnnotationText("Sagittal"); renderWindowWidget2->GetRenderWindow()->SetLayoutIndex(ViewDirection::SAGITTAL); AddRenderWindowWidget(renderWindowWidgetName, renderWindowWidget2); // create coronal render window (widget) renderWindowWidgetName = GetNameFromIndex(1, 0); RenderWindowWidgetPointer renderWindowWidget3 = std::make_shared(this, renderWindowWidgetName, GetDataStorage(), GetRenderingManager()); auto renderWindow3 = renderWindowWidget3->GetRenderWindow(); renderWindow3->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Frontal); renderWindowWidget3->SetDecorationColor(GetDecorationColor(2)); renderWindowWidget3->SetCornerAnnotationText("Coronal"); renderWindowWidget3->GetRenderWindow()->SetLayoutIndex(ViewDirection::CORONAL); AddRenderWindowWidget(renderWindowWidgetName, renderWindowWidget3); // create 3D render window (widget) renderWindowWidgetName = GetNameFromIndex(1, 1); RenderWindowWidgetPointer renderWindowWidget4 = std::make_shared(this, renderWindowWidgetName, GetDataStorage(), GetRenderingManager()); auto renderWindow4 = renderWindowWidget4->GetRenderWindow(); renderWindow4->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Original); renderWindowWidget4->SetDecorationColor(GetDecorationColor(3)); renderWindowWidget4->SetCornerAnnotationText("3D"); renderWindowWidget4->GetRenderWindow()->SetLayoutIndex(ViewDirection::THREE_D); mitk::BaseRenderer::GetInstance(renderWindowWidget4->GetRenderWindow()->GetRenderWindow())->SetMapperID(mitk::BaseRenderer::Standard3D); AddRenderWindowWidget(renderWindowWidgetName, renderWindowWidget4); SetActiveRenderWindowWidget(renderWindowWidget1); // connect to the "time navigation controller": send time via sliceNavigationControllers m_TimeNavigationController->ConnectGeometryTimeEvent(renderWindow1->GetSliceNavigationController(), false); m_TimeNavigationController->ConnectGeometryTimeEvent(renderWindow2->GetSliceNavigationController(), false); m_TimeNavigationController->ConnectGeometryTimeEvent(renderWindow3->GetSliceNavigationController(), false); m_TimeNavigationController->ConnectGeometryTimeEvent(renderWindow4->GetSliceNavigationController(), false); renderWindow1->GetSliceNavigationController()->ConnectGeometrySendEvent( mitk::BaseRenderer::GetInstance(renderWindow4->GetRenderWindow())); // reverse connection between sliceNavigationControllers and timeNavigationController renderWindow1->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); renderWindow2->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); renderWindow3->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); //renderWindow4->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); auto layoutManager = GetMultiWidgetLayoutManager(); connect(renderWindowWidget1.get(), &QmitkRenderWindowWidget::MouseEvent, this, &QmitkStdMultiWidget::mousePressEvent); connect(renderWindow1, &QmitkRenderWindow::ResetView, this, &QmitkStdMultiWidget::ResetCrosshair); connect(renderWindow1, &QmitkRenderWindow::CrosshairVisibilityChanged, this, &QmitkStdMultiWidget::SetCrosshairVisibility); connect(renderWindow1, &QmitkRenderWindow::CrosshairRotationModeChanged, this, &QmitkStdMultiWidget::SetWidgetPlaneMode); connect(renderWindow1, &QmitkRenderWindow::LayoutDesignChanged, layoutManager, &QmitkMultiWidgetLayoutManager::SetLayoutDesign); connect(renderWindowWidget2.get(), &QmitkRenderWindowWidget::MouseEvent, this, &QmitkStdMultiWidget::mousePressEvent); connect(renderWindow2, &QmitkRenderWindow::ResetView, this, &QmitkStdMultiWidget::ResetCrosshair); connect(renderWindow2, &QmitkRenderWindow::CrosshairVisibilityChanged, this, &QmitkStdMultiWidget::SetCrosshairVisibility); connect(renderWindow2, &QmitkRenderWindow::CrosshairRotationModeChanged, this, &QmitkStdMultiWidget::SetWidgetPlaneMode); connect(renderWindow2, &QmitkRenderWindow::LayoutDesignChanged, layoutManager, &QmitkMultiWidgetLayoutManager::SetLayoutDesign); connect(renderWindowWidget3.get(), &QmitkRenderWindowWidget::MouseEvent, this, &QmitkStdMultiWidget::mousePressEvent); connect(renderWindow3, &QmitkRenderWindow::ResetView, this, &QmitkStdMultiWidget::ResetCrosshair); connect(renderWindow3, &QmitkRenderWindow::CrosshairVisibilityChanged, this, &QmitkStdMultiWidget::SetCrosshairVisibility); connect(renderWindow3, &QmitkRenderWindow::CrosshairRotationModeChanged, this, &QmitkStdMultiWidget::SetWidgetPlaneMode); connect(renderWindow3, &QmitkRenderWindow::LayoutDesignChanged, layoutManager, &QmitkMultiWidgetLayoutManager::SetLayoutDesign); connect(renderWindowWidget4.get(), &QmitkRenderWindowWidget::MouseEvent, this, &QmitkStdMultiWidget::mousePressEvent); connect(renderWindow4, &QmitkRenderWindow::ResetView, this, &QmitkStdMultiWidget::ResetCrosshair); connect(renderWindow4, &QmitkRenderWindow::CrosshairVisibilityChanged, this, &QmitkStdMultiWidget::SetCrosshairVisibility); connect(renderWindow4, &QmitkRenderWindow::CrosshairRotationModeChanged, this, &QmitkStdMultiWidget::SetWidgetPlaneMode); connect(renderWindow4, &QmitkRenderWindow::LayoutDesignChanged, layoutManager, &QmitkMultiWidgetLayoutManager::SetLayoutDesign); } diff --git a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/QmitkStdMultiWidgetEditor.cpp b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/QmitkStdMultiWidgetEditor.cpp index ec3c92b0ed..1fb88d109c 100644 --- a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/QmitkStdMultiWidgetEditor.cpp +++ b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/QmitkStdMultiWidgetEditor.cpp @@ -1,410 +1,412 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkStdMultiWidgetEditor.h" #include #include #include #include #include #include #include #include #include // mitk qt widgets module #include #include #include #include // mitk gui qt common plugin #include const QString QmitkStdMultiWidgetEditor::EDITOR_ID = "org.mitk.editors.stdmultiwidget"; struct QmitkStdMultiWidgetEditor::Impl final { Impl(); ~Impl() = default; QmitkInteractionSchemeToolBar* m_InteractionSchemeToolBar; QmitkLevelWindowWidget* m_LevelWindowWidget; std::unique_ptr m_MultiWidgetDecorationManager; }; QmitkStdMultiWidgetEditor::Impl::Impl() : m_InteractionSchemeToolBar(nullptr) , m_LevelWindowWidget(nullptr) { // nothing here } ////////////////////////////////////////////////////////////////////////// // QmitkStdMultiWidgetEditor ////////////////////////////////////////////////////////////////////////// QmitkStdMultiWidgetEditor::QmitkStdMultiWidgetEditor() : QmitkAbstractMultiWidgetEditor() , m_Impl(std::make_unique()) { // nothing here } QmitkStdMultiWidgetEditor::~QmitkStdMultiWidgetEditor() { GetSite()->GetPage()->RemovePartListener(this); } berry::IPartListener::Events::Types QmitkStdMultiWidgetEditor::GetPartEventTypes() const { return Events::CLOSED | Events::OPENED | Events::HIDDEN | Events::VISIBLE; } void QmitkStdMultiWidgetEditor::PartClosed(const berry::IWorkbenchPartReference::Pointer& partRef) { if (partRef->GetId() == QmitkStdMultiWidgetEditor::EDITOR_ID) { const auto& multiWidget = dynamic_cast(GetMultiWidget()); if (nullptr != multiWidget) { multiWidget->RemovePlanesFromDataStorage(); multiWidget->ActivateMenuWidget(false); } } } void QmitkStdMultiWidgetEditor::PartOpened(const berry::IWorkbenchPartReference::Pointer& partRef) { if (partRef->GetId() == QmitkStdMultiWidgetEditor::EDITOR_ID) { const auto& multiWidget = dynamic_cast(GetMultiWidget()); if (nullptr != multiWidget) { multiWidget->AddPlanesToDataStorage(); multiWidget->ActivateMenuWidget(true); } } } void QmitkStdMultiWidgetEditor::PartHidden(const berry::IWorkbenchPartReference::Pointer& partRef) { if (partRef->GetId() == QmitkStdMultiWidgetEditor::EDITOR_ID) { const auto& multiWidget = dynamic_cast(GetMultiWidget()); if (nullptr != multiWidget) { multiWidget->ActivateMenuWidget(false); } } } void QmitkStdMultiWidgetEditor::PartVisible(const berry::IWorkbenchPartReference::Pointer& partRef) { if (partRef->GetId() == QmitkStdMultiWidgetEditor::EDITOR_ID) { const auto& multiWidget = dynamic_cast(GetMultiWidget()); if (nullptr != multiWidget) { multiWidget->ActivateMenuWidget(true); } } } QmitkLevelWindowWidget* QmitkStdMultiWidgetEditor::GetLevelWindowWidget() const { return m_Impl->m_LevelWindowWidget; } void QmitkStdMultiWidgetEditor::EnableSlicingPlanes(bool enable) { const auto& multiWidget = dynamic_cast(GetMultiWidget()); if (nullptr == multiWidget) { return; } - + multiWidget->SetWidgetPlanesVisibility(enable); } bool QmitkStdMultiWidgetEditor::IsSlicingPlanesEnabled() const { const auto& multiWidget = dynamic_cast(GetMultiWidget()); if (nullptr == multiWidget) { return false; } mitk::DataNode::Pointer node = multiWidget->GetWidgetPlane1(); if (node.IsNotNull()) { bool visible = false; node->GetVisibility(visible, nullptr); return visible; } else { return false; } } void QmitkStdMultiWidgetEditor::OnInteractionSchemeChanged(mitk::InteractionSchemeSwitcher::InteractionScheme scheme) { const auto& multiWidget = GetMultiWidget(); if (nullptr == multiWidget) { return; } if (mitk::InteractionSchemeSwitcher::PACSStandard == scheme) { m_Impl->m_InteractionSchemeToolBar->setVisible(true); } else { m_Impl->m_InteractionSchemeToolBar->setVisible(false); } QmitkAbstractMultiWidgetEditor::OnInteractionSchemeChanged(scheme); } void QmitkStdMultiWidgetEditor::ShowLevelWindowWidget(bool show) { if (show) { m_Impl->m_LevelWindowWidget->disconnect(this); m_Impl->m_LevelWindowWidget->SetDataStorage(GetDataStorage()); m_Impl->m_LevelWindowWidget->show(); } else { m_Impl->m_LevelWindowWidget->disconnect(this); m_Impl->m_LevelWindowWidget->hide(); } } void QmitkStdMultiWidgetEditor::SetFocus() { const auto& multiWidget = GetMultiWidget(); if (nullptr != multiWidget) { multiWidget->setFocus(); } } void QmitkStdMultiWidgetEditor::CreateQtPartControl(QWidget* parent) { QHBoxLayout* layout = new QHBoxLayout(parent); layout->setContentsMargins(0, 0, 0, 0); berry::IBerryPreferences* preferences = dynamic_cast(GetPreferences().GetPointer()); auto multiWidget = GetMultiWidget(); if (nullptr == multiWidget) { - mitk::BaseRenderer::RenderingMode::Type renderingMode = static_cast(preferences->GetInt("Rendering Mode", 0)); + auto renderingMode = static_cast( + prefs->GetInt("Rendering Mode", static_cast(mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing))); + multiWidget = new QmitkStdMultiWidget(parent, 0, nullptr, renderingMode); // create left toolbar: interaction scheme toolbar to switch how the render window navigation behaves (in PACS mode) if (nullptr == m_Impl->m_InteractionSchemeToolBar) { m_Impl->m_InteractionSchemeToolBar = new QmitkInteractionSchemeToolBar(parent); layout->addWidget(m_Impl->m_InteractionSchemeToolBar); } m_Impl->m_InteractionSchemeToolBar->SetInteractionEventHandler(multiWidget->GetInteractionEventHandler()); multiWidget->SetDataStorage(GetDataStorage()); multiWidget->InitializeMultiWidget(); SetMultiWidget(multiWidget); } layout->addWidget(multiWidget); // create level window slider on the right side if (nullptr == m_Impl->m_LevelWindowWidget) { m_Impl->m_LevelWindowWidget = new QmitkLevelWindowWidget(parent); m_Impl->m_LevelWindowWidget->setObjectName(QString::fromUtf8("levelWindowWidget")); QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); sizePolicy.setHeightForWidth(m_Impl->m_LevelWindowWidget->sizePolicy().hasHeightForWidth()); m_Impl->m_LevelWindowWidget->setSizePolicy(sizePolicy); m_Impl->m_LevelWindowWidget->setMaximumWidth(50); } layout->addWidget(m_Impl->m_LevelWindowWidget); m_Impl->m_MultiWidgetDecorationManager = std::make_unique(multiWidget); GetSite()->GetPage()->AddPartListener(this); InitializePreferences(preferences); OnPreferencesChanged(preferences); } void QmitkStdMultiWidgetEditor::OnPreferencesChanged(const berry::IBerryPreferences* preferences) { const auto& multiWidget = dynamic_cast(GetMultiWidget()); if (nullptr == multiWidget) { return; } // change and apply decoration preferences GetPreferenceDecorations(preferences); m_Impl->m_MultiWidgetDecorationManager->DecorationPreferencesChanged(preferences); QmitkAbstractMultiWidget::RenderWindowWidgetMap renderWindowWidgets = multiWidget->GetRenderWindowWidgets(); int i = 0; for (const auto& renderWindowWidget : renderWindowWidgets) { auto decorationColor = renderWindowWidget.second->GetDecorationColor(); multiWidget->SetDecorationColor(i, decorationColor); ++i; } int crosshairgapsize = preferences->GetInt("crosshair gap size", 32); multiWidget->GetWidgetPlane1()->SetIntProperty("Crosshair.Gap Size", crosshairgapsize); multiWidget->GetWidgetPlane2()->SetIntProperty("Crosshair.Gap Size", crosshairgapsize); multiWidget->GetWidgetPlane3()->SetIntProperty("Crosshair.Gap Size", crosshairgapsize); // zooming and panning preferences bool constrainedZooming = preferences->GetBool("Use constrained zooming and panning", true); mitk::RenderingManager::GetInstance()->SetConstrainedPanningZooming(constrainedZooming); // mouse modes switcher toolbar bool PACSInteractionScheme = preferences->GetBool("PACS like mouse interaction", false); OnInteractionSchemeChanged(PACSInteractionScheme ? mitk::InteractionSchemeSwitcher::PACSStandard : mitk::InteractionSchemeSwitcher::MITKStandard); // level window setting bool showLevelWindowWidget = preferences->GetBool("Show level/window widget", true); ShowLevelWindowWidget(showLevelWindowWidget); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(GetDataStorage()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkStdMultiWidgetEditor::InitializePreferences(berry::IBerryPreferences * preferences) { auto multiWidget = GetMultiWidget(); if (nullptr == multiWidget) { return; } GetPreferenceDecorations(preferences); //overwrite if preferences are defined QmitkAbstractMultiWidget::RenderWindowWidgetMap renderWindowWidgets = multiWidget->GetRenderWindowWidgets(); int i = 0; for (const auto& renderWindowWidget : renderWindowWidgets) { QString widgetName = "widget" + QString::number(i + 1); auto gradientBackgroundColors = renderWindowWidget.second->GetGradientBackgroundColors(); preferences->Put(widgetName + " first background color", MitkColorToHex(gradientBackgroundColors.first)); preferences->Put(widgetName + " second background color", MitkColorToHex(gradientBackgroundColors.second)); auto decorationColor = renderWindowWidget.second->GetDecorationColor(); preferences->Put(widgetName + " decoration color", MitkColorToHex(decorationColor)); auto cornerAnnotation = renderWindowWidget.second->GetCornerAnnotationText(); preferences->Put(widgetName + " corner annotation", QString::fromStdString(cornerAnnotation)); ++i; } } void QmitkStdMultiWidgetEditor::GetPreferenceDecorations(const berry::IBerryPreferences * preferences) { auto multiWidget = dynamic_cast(GetMultiWidget()); if (nullptr == multiWidget) { return; } auto hexBlack = "#000000"; auto gradientBlack = "#191919"; auto gradientGray = "#7F7F7F"; auto renderWindowWidgets = multiWidget->GetRenderWindowWidgets(); int i = 0; for (const auto& renderWindowWidget : renderWindowWidgets) { QString widgetName = renderWindowWidget.second->GetWidgetName(); if (mitk::BaseRenderer::Standard3D == mitk::BaseRenderer::GetInstance(renderWindowWidget.second->GetRenderWindow()->GetVtkRenderWindow())->GetMapperID()) { auto upper = preferences->Get(widgetName + " first background color", gradientBlack); auto lower = preferences->Get(widgetName + " second background color", gradientGray); renderWindowWidget.second->SetGradientBackgroundColors(HexColorToMitkColor(upper), HexColorToMitkColor(lower)); } else { auto upper = preferences->Get(widgetName + " first background color", hexBlack); auto lower = preferences->Get(widgetName + " second background color", hexBlack); renderWindowWidget.second->SetGradientBackgroundColors(HexColorToMitkColor(upper), HexColorToMitkColor(lower)); } auto defaultDecorationColor = multiWidget->GetDecorationColor(i); auto decorationColor = preferences->Get(widgetName + " decoration color", MitkColorToHex(defaultDecorationColor)); renderWindowWidget.second->SetDecorationColor(HexColorToMitkColor(decorationColor)); - + auto defaultCornerAnnotation = renderWindowWidget.second->GetCornerAnnotationText(); auto cornerAnnotation = preferences->Get(widgetName + " corner annotation", QString::fromStdString(defaultCornerAnnotation)); renderWindowWidget.second->SetCornerAnnotationText(cornerAnnotation.toStdString()); ++i; } } mitk::Color QmitkStdMultiWidgetEditor::HexColorToMitkColor(const QString& hexColor) { QColor qColor(hexColor); mitk::Color returnColor; float colorMax = 255.0f; if (hexColor.isEmpty()) // default value { returnColor[0] = 1.0; returnColor[1] = 1.0; returnColor[2] = 1.0; MITK_ERROR << "Using default color for unknown hex color " << qPrintable(hexColor); } else { returnColor[0] = qColor.red() / colorMax; returnColor[1] = qColor.green() / colorMax; returnColor[2] = qColor.blue() / colorMax; } return returnColor; } QString QmitkStdMultiWidgetEditor::MitkColorToHex(const mitk::Color& color) { QColor returnColor; float colorMax = 255.0f; returnColor.setRed(static_cast(color[0] * colorMax + 0.5)); returnColor.setGreen(static_cast(color[1] * colorMax + 0.5)); returnColor.setBlue(static_cast(color[2] * colorMax + 0.5)); return returnColor.name(); } diff --git a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.cpp b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.cpp index 3f3ce8590f..203887ca51 100644 --- a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.cpp +++ b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.cpp @@ -1,267 +1,294 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include #include "QmitkStdMultiWidgetEditorPreferencePage.h" +#include #include +#include + #include #include +#include +#include + #include + +namespace +{ + void ChangeRenderingMode(mitk::BaseRenderer::RenderingMode renderingMode) + { + auto renderingManager = mitk::RenderingManager::GetInstance(); + + if (nullptr == renderingManager) + return; + + auto renderWindows = renderingManager->GetAllRegisteredRenderWindows(); + + for (auto renderWindow : renderWindows) + { + auto renderers = renderWindow->GetRenderers(); + + if (nullptr != renderers) + { + renderers->InitTraversal(); + auto renderer = renderers->GetNextItem(); + + while (nullptr != renderer) + { + renderer->SetUseFXAA(mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing == renderingMode); + renderer = renderers->GetNextItem(); + } + + renderingManager->RequestUpdate(renderWindow); + } + } + } +} + QmitkStdMultiWidgetEditorPreferencePage::QmitkStdMultiWidgetEditorPreferencePage() : m_Preferences(nullptr), m_Ui(new Ui::QmitkStdMultiWidgetEditorPreferencePage), m_Control(nullptr) { } QmitkStdMultiWidgetEditorPreferencePage::~QmitkStdMultiWidgetEditorPreferencePage() { } void QmitkStdMultiWidgetEditorPreferencePage::CreateQtControl(QWidget* parent) { m_Control = new QWidget(parent); m_Ui->setupUi(m_Control); berry::IPreferencesService* prefService = berry::Platform::GetPreferencesService(); Q_ASSERT(prefService); m_Preferences = prefService->GetSystemPreferences()->Node(QmitkStdMultiWidgetEditor::EDITOR_ID); QObject::connect( m_Ui->m_ColorButton1, SIGNAL( clicked() ) , this, SLOT( ColorChooserButtonClicked() ) ); QObject::connect( m_Ui->m_ColorButton2, SIGNAL( clicked() ) , this, SLOT( ColorChooserButtonClicked() ) ); QObject::connect( m_Ui->m_ResetButton, SIGNAL( clicked() ) , this, SLOT( ResetPreferencesAndGUI() ) ); - QObject::connect( m_Ui->m_RenderingMode, SIGNAL(activated(int) ) - , this, SLOT( ChangeRenderingMode(int) ) ); - QObject::connect( m_Ui->m_RenderWindowDecorationColor, SIGNAL( clicked() ) , this, SLOT( ColorChooserButtonClicked() ) ); QObject::connect( m_Ui->m_RenderWindowChooser, SIGNAL(activated(int) ) , this, SLOT( OnWidgetComboBoxChanged(int) ) ); QObject::connect( m_Ui->m_RenderWindowDecorationText, SIGNAL(textChanged(QString) ) , this, SLOT( AnnotationTextChanged(QString) ) ); this->Update(); } QWidget* QmitkStdMultiWidgetEditorPreferencePage::GetQtControl() const { return m_Control; } void QmitkStdMultiWidgetEditorPreferencePage::Init(berry::IWorkbench::Pointer) { } void QmitkStdMultiWidgetEditorPreferencePage::PerformCancel() { } bool QmitkStdMultiWidgetEditorPreferencePage::PerformOk() { m_Preferences->Put("stdmulti.widget0 corner annotation", m_WidgetAnnotation[0]); m_Preferences->Put("stdmulti.widget1 corner annotation", m_WidgetAnnotation[1]); m_Preferences->Put("stdmulti.widget2 corner annotation", m_WidgetAnnotation[2]); m_Preferences->Put("stdmulti.widget3 corner annotation", m_WidgetAnnotation[3]); m_Preferences->Put("stdmulti.widget0 decoration color", m_WidgetDecorationColor[0]); m_Preferences->Put("stdmulti.widget1 decoration color", m_WidgetDecorationColor[1]); m_Preferences->Put("stdmulti.widget2 decoration color", m_WidgetDecorationColor[2]); m_Preferences->Put("stdmulti.widget3 decoration color", m_WidgetDecorationColor[3]); m_Preferences->Put("stdmulti.widget0 first background color", m_WidgetBackgroundColor1[0]); m_Preferences->Put("stdmulti.widget1 first background color", m_WidgetBackgroundColor1[1]); m_Preferences->Put("stdmulti.widget2 first background color", m_WidgetBackgroundColor1[2]); m_Preferences->Put("stdmulti.widget3 first background color", m_WidgetBackgroundColor1[3]); m_Preferences->Put("stdmulti.widget0 second background color", m_WidgetBackgroundColor2[0]); m_Preferences->Put("stdmulti.widget1 second background color", m_WidgetBackgroundColor2[1]); m_Preferences->Put("stdmulti.widget2 second background color", m_WidgetBackgroundColor2[2]); m_Preferences->Put("stdmulti.widget3 second background color", m_WidgetBackgroundColor2[3]); m_Preferences->PutInt("crosshair gap size", m_Ui->m_CrosshairGapSize->value()); m_Preferences->PutBool("Use constrained zooming and panning" , m_Ui->m_EnableFlexibleZooming->isChecked()); m_Preferences->PutBool("Show level/window widget", m_Ui->m_ShowLevelWindowWidget->isChecked()); m_Preferences->PutBool("PACS like mouse interaction", m_Ui->m_PACSLikeMouseMode->isChecked()); - m_Preferences->PutInt("Rendering Mode", m_Ui->m_RenderingMode->currentIndex()); + + auto renderingMode = static_cast(m_Ui->m_RenderingMode->currentIndex()); + m_Preferences->PutInt("Rendering Mode", static_cast(renderingMode)); + ChangeRenderingMode(renderingMode); // Change the rendering mode now, no restart required return true; } void QmitkStdMultiWidgetEditorPreferencePage::Update() { //Note: there should be default preferences already defined in the //QmitkStdMultiWidgetEditor::InitializePreferences(). Therefore, //all default values here are not relevant. //gradient background colors m_WidgetBackgroundColor1[0] = m_Preferences->Get("stdmulti.widget0 first background color", "#1d1d1c"); m_WidgetBackgroundColor2[0] = m_Preferences->Get("stdmulti.widget0 second background color", "#1d1d1c"); m_WidgetBackgroundColor1[1] = m_Preferences->Get("stdmulti.widget1 first background color", "#1d1d1c"); m_WidgetBackgroundColor2[1] = m_Preferences->Get("stdmulti.widget1 second background color", "#1d1d1c"); m_WidgetBackgroundColor1[2] = m_Preferences->Get("stdmulti.widget2 first background color", "#1d1d1c"); m_WidgetBackgroundColor2[2] = m_Preferences->Get("stdmulti.widget2 second background color", "#1d1d1c"); m_WidgetBackgroundColor1[3] = m_Preferences->Get("stdmulti.widget3 first background color", "#1d1d1c"); m_WidgetBackgroundColor2[3] = m_Preferences->Get("stdmulti.widget3 second background color", "#adb1b6"); //decoration colors m_WidgetDecorationColor[0] = m_Preferences->Get("stdmulti.widget0 decoration color", "#c00000"); m_WidgetDecorationColor[1] = m_Preferences->Get("stdmulti.widget1 decoration color", "#0fad00"); m_WidgetDecorationColor[2] = m_Preferences->Get("stdmulti.widget2 decoration color", "#0080ff"); m_WidgetDecorationColor[3] = m_Preferences->Get("stdmulti.widget3 decoration color", "#fec500"); //annotation text m_WidgetAnnotation[0] = m_Preferences->Get("stdmulti.widget0 corner annotation", "Axial"); m_WidgetAnnotation[1] = m_Preferences->Get("stdmulti.widget1 corner annotation", "Sagittal"); m_WidgetAnnotation[2] = m_Preferences->Get("stdmulti.widget2 corner annotation", "Coronal"); m_WidgetAnnotation[3] = m_Preferences->Get("stdmulti.widget3 corner annotation", "3D"); //Ui stuff int index = m_Ui->m_RenderWindowChooser->currentIndex(); QColor firstBackgroundColor(m_WidgetBackgroundColor1[index]); QColor secondBackgroundColor(m_WidgetBackgroundColor2[index]); QColor widgetColor(m_WidgetDecorationColor[index]); this->SetStyleSheetToColorChooserButton(firstBackgroundColor, m_Ui->m_ColorButton1); this->SetStyleSheetToColorChooserButton(secondBackgroundColor, m_Ui->m_ColorButton2); this->SetStyleSheetToColorChooserButton(widgetColor, m_Ui->m_RenderWindowDecorationColor); m_Ui->m_RenderWindowDecorationText->setText(m_WidgetAnnotation[index]); m_Ui->m_EnableFlexibleZooming->setChecked(m_Preferences->GetBool("Use constrained zooming and panning", true)); m_Ui->m_ShowLevelWindowWidget->setChecked(m_Preferences->GetBool("Show level/window widget", true)); m_Ui->m_PACSLikeMouseMode->setChecked(m_Preferences->GetBool("PACS like mouse interaction", false)); - int mode = m_Preferences->GetInt("Rendering Mode", 1); - m_Ui->m_RenderingMode->setCurrentIndex(mode); m_Ui->m_CrosshairGapSize->setValue(m_Preferences->GetInt("crosshair gap size", 32)); + + auto renderingMode = m_Preferences->GetInt("Rendering Mode", static_cast(mitk::BaseRenderer::RenderingMode::FastApproximateAntiAliasing)); + m_Ui->m_RenderingMode->setCurrentIndex(renderingMode); } void QmitkStdMultiWidgetEditorPreferencePage::ColorChooserButtonClicked() { unsigned int widgetIndex = m_Ui->m_RenderWindowChooser->currentIndex(); if(widgetIndex > 3) { MITK_ERROR << "Selected index for unknown."; return; } QObject *senderObj = sender(); // This will give Sender button //find out last used color and set it QColor initialColor; if( senderObj->objectName() == m_Ui->m_ColorButton1->objectName()) { initialColor = QColor(m_WidgetBackgroundColor1[widgetIndex]); }else if( senderObj->objectName() == m_Ui->m_ColorButton2->objectName()) { initialColor = QColor(m_WidgetBackgroundColor2[widgetIndex]); }else if( senderObj->objectName() == m_Ui->m_RenderWindowDecorationColor->objectName()) { initialColor = QColor(m_WidgetDecorationColor[widgetIndex]); } //get the new color QColor newcolor = QColorDialog::getColor(initialColor); if(!newcolor.isValid()) { newcolor = initialColor; } this->SetStyleSheetToColorChooserButton(newcolor, static_cast(senderObj)); //convert it to std string and apply it if( senderObj->objectName() == m_Ui->m_ColorButton1->objectName()) { m_WidgetBackgroundColor1[widgetIndex] = newcolor.name(); } else if( senderObj->objectName() == m_Ui->m_ColorButton2->objectName()) { m_WidgetBackgroundColor2[widgetIndex] = newcolor.name(); } else if( senderObj->objectName() == m_Ui->m_RenderWindowDecorationColor->objectName()) { m_WidgetDecorationColor[widgetIndex] = newcolor.name(); } } void QmitkStdMultiWidgetEditorPreferencePage::SetStyleSheetToColorChooserButton(QColor backgroundcolor, QPushButton* button) { button->setAutoFillBackground(true); QString styleSheet = "background-color:rgb("; styleSheet.append(QString::number(backgroundcolor.red())); styleSheet.append(","); styleSheet.append(QString::number(backgroundcolor.green())); styleSheet.append(","); styleSheet.append(QString::number(backgroundcolor.blue())); styleSheet.append(")"); button->setStyleSheet(styleSheet); } void QmitkStdMultiWidgetEditorPreferencePage::AnnotationTextChanged(QString text) { unsigned int widgetIndex = m_Ui->m_RenderWindowChooser->currentIndex(); if( widgetIndex > 3) { MITK_INFO << "Selected index for unknown widget."; return; } m_WidgetAnnotation[widgetIndex] = text; } void QmitkStdMultiWidgetEditorPreferencePage::ResetPreferencesAndGUI() { m_Preferences->Clear(); this->Update(); } void QmitkStdMultiWidgetEditorPreferencePage::OnWidgetComboBoxChanged(int i) { if( i > 3) { MITK_ERROR << "Selected unknown widget."; return; } QColor widgetColor(m_WidgetDecorationColor[i]); QColor gradientBackground1(m_WidgetBackgroundColor1[i]); QColor gradientBackground2(m_WidgetBackgroundColor2[i]); this->SetStyleSheetToColorChooserButton(widgetColor, m_Ui->m_RenderWindowDecorationColor); this->SetStyleSheetToColorChooserButton(gradientBackground1, m_Ui->m_ColorButton1); this->SetStyleSheetToColorChooserButton(gradientBackground2, m_Ui->m_ColorButton2); m_Ui->m_RenderWindowDecorationText->setText(m_WidgetAnnotation[i]); } - -void QmitkStdMultiWidgetEditorPreferencePage::ChangeRenderingMode(int i) -{ - if (0 == i) - { - m_CurrentRenderingMode = "No Anti-aliasing"; - } - else if (1 == i) - { - m_CurrentRenderingMode = "Fast Approximate Anti-Aliasing (FXAA)"; - } -} diff --git a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.h b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.h index a74071032b..6253c9ea67 100644 --- a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.h +++ b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.h @@ -1,120 +1,109 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkStdMultiWidgetEditorPreferencePage_h #define QmitkStdMultiWidgetEditorPreferencePage_h #include #include #include #include #include namespace Ui { class QmitkStdMultiWidgetEditorPreferencePage; } class QmitkStdMultiWidgetEditorPreferencePage : public QObject, public berry::IQtPreferencePage { Q_OBJECT Q_INTERFACES(berry::IPreferencePage) public: QmitkStdMultiWidgetEditorPreferencePage(); ~QmitkStdMultiWidgetEditorPreferencePage() override; void CreateQtControl(QWidget* parent) override; QWidget* GetQtControl() const override; void Init(berry::IWorkbench::Pointer) override; void PerformCancel() override; bool PerformOk() override; void Update() override; public slots: /** * @brief ResetColors set default colors and refresh the GUI. */ void ResetPreferencesAndGUI(); - /** - * @brief ChangeRenderingMode slot to chose the rendering mode via QComboBox. - * @param i index of the box. - */ - void ChangeRenderingMode(int i); - /** * @brief OnWidgetComboBoxChanged slot called when the QComboBox to chose the widget was modified. * @param i index of the combobox to select the widget (1-4). */ void OnWidgetComboBoxChanged(int i); /** * @brief AnnotationTextChanged called when QLineEdit for the annotation was changed. * @param text The new text. */ void AnnotationTextChanged(QString text); protected: - /** - * @brief m_CurrentRenderingMode String for the rendering mode. - */ - std::string m_CurrentRenderingMode; - /** * @brief m_WidgetBackgroundColor1 the background colors. * * If two different colors are chosen, a gradient background appears. */ QString m_WidgetBackgroundColor1[4]; QString m_WidgetBackgroundColor2[4]; /** * @brief m_WidgetDecorationColor the decoration color. * * The rectangle prop, the crosshair, the 3D planes and the corner annotation use this. */ QString m_WidgetDecorationColor[4]; /** * @brief m_Widget1Annotation the text of the corner annotation. */ QString m_WidgetAnnotation[4]; /** * @brief m_Preferences the berry preferences. */ berry::IPreferences::Pointer m_Preferences; /** * @brief SetStyleSheetToColorChooserButton colorize a button. * @param backgroundcolor color for the button. * @param button the button. */ void SetStyleSheetToColorChooserButton(QColor backgroundcolor, QPushButton* button); protected slots: /** * @brief ColorChooserButtonClicked slot called when a button to choose color was clicked. */ void ColorChooserButtonClicked(); private: QScopedPointer m_Ui; QWidget* m_Control; }; #endif //QmitkStdMultiWidgetEditorPreferencePage_h diff --git a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.ui b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.ui index e0a9d50f14..8f9ed01e88 100644 --- a/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.ui +++ b/Plugins/org.mitk.gui.qt.stdmultiwidgeteditor/src/internal/QmitkStdMultiWidgetEditorPreferencePage.ui @@ -1,217 +1,223 @@ QmitkStdMultiWidgetEditorPreferencePage 0 0 518 - 431 + 730 External Programs - - - - - stdmulti.widget1 - - - - - stdmulti.widget2 - - - - - stdmulti.widget3 - - - - - stdmulti.widget4 - - + + + + The small text on the button left of each renderwindow. + + + Corner annotation + - + <html><head/><body><p>If two colors are set, a gradient background is generated.</p></body></html> Background color - - + + - Reset preferences + - - + + - No anti-aliasing + stdmulti.widget1 - Fast Approximate Anti-Aliasing (FXAA) + stdmulti.widget2 + + + + + stdmulti.widget3 + + + + + stdmulti.widget4 - - + + + + <html><head/><body><p>The color is used for the following decorations (of each renderwindow):</p><p>Rectangle border</p><p>Corner annotation</p><p>Crosshair</p><p>Plane geometry helper objects (3D Planes)</p><p>Image navigator borders</p><p><br/></p></body></html> + - * Changes require restart of MITK. + Decoration color - + 32 - - + + Qt::Horizontal - - - - The small text on the button left of each renderwindow. - - - Corner annotation + + + + Qt::Horizontal - - - - <html><head/><body><p>The gap in the middle of the crosshair in pixels.</p></body></html> + + + + Qt::LeftToRight - Crosshair gap size - - - - - - - <html><head/><body><p>The color is used for the following decorations (of each renderwindow):</p><p>Rectangle border</p><p>Corner annotation</p><p>Crosshair</p><p>Plane geometry helper objects (3D Planes)</p><p>Image navigator borders</p><p><br/></p></body></html> + Use PACS like mouse interaction (select left mouse button action) - - Decoration color + + false - - + + - + Reset preferences - - + + - <html><head/><body><p>Choose the renderwindow from the multi widget.</p></body></html> - - - Render windows + <html><head/><body><p>If activated, zooming and panning is limited to a certain space arround each image.</p></body></html> - - - - Qt::LeftToRight - Show level/window widget + Use constraint zooming and panning true - - - - Qt::LeftToRight + + + + <html><head/><body><p>Choose the renderwindow from the multi widget.</p></body></html> - Use PACS like mouse interaction (select left mouse button action) - - - false + Render windows - - + + - - - - Qt::Horizontal - + + + + + + + + No anti-aliasing + + + + + Fast Approximate Anti-Aliasing (FXAA) + + - - + + + + <html><head/><body><p>The gap in the middle of the crosshair in pixels.</p></body></html> + - Rendering Mode* + Crosshair gap size - - - - + - - - - <html><head/><body><p>If activated, zooming and panning is limited to a certain space arround each image.</p></body></html> + + + + Rendering mode + + + + Qt::LeftToRight - Use constraint zooming and panning + Show level/window widget true + + + + Qt::Vertical + + + + 20 + 40 + + + +