diff --git a/CMakeExternals/VTK.cmake b/CMakeExternals/VTK.cmake index 1e27a03e16..abcb30c254 100644 --- a/CMakeExternals/VTK.cmake +++ b/CMakeExternals/VTK.cmake @@ -1,117 +1,118 @@ #----------------------------------------------------------------------------- # VTK #----------------------------------------------------------------------------- if(WIN32) option(VTK_USE_SYSTEM_FREETYPE OFF) else(WIN32) option(VTK_USE_SYSTEM_FREETYPE ON) endif(WIN32) # Sanity checks if(DEFINED VTK_DIR AND NOT EXISTS ${VTK_DIR}) message(FATAL_ERROR "VTK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj VTK) set(proj_DEPENDENCIES ) set(VTK_DEPENDS ${proj}) if(MITK_USE_HDF5) list(APPEND proj_DEPENDENCIES HDF5) endif() if(NOT DEFINED VTK_DIR) set(additional_cmake_args ) if(MINGW) set(additional_cmake_args -DCMAKE_USE_WIN32_THREADS:BOOL=ON -DCMAKE_USE_PTHREADS:BOOL=OFF -DVTK_USE_VIDEO4WINDOWS:BOOL=OFF # no header files provided by MinGW ) endif() # Optionally enable memory leak checks for any objects derived from vtkObject. This # will force unit tests to fail if they have any of these memory leaks. option(MITK_VTK_DEBUG_LEAKS OFF) mark_as_advanced(MITK_VTK_DEBUG_LEAKS) list(APPEND additional_cmake_args -DVTK_DEBUG_LEAKS:BOOL=${MITK_VTK_DEBUG_LEAKS} ) if(MITK_USE_Python) if(NOT MITK_USE_SYSTEM_PYTHON) list(APPEND proj_DEPENDENCIES Python) set(_vtk_install_python_dir -DVTK_INSTALL_PYTHON_MODULE_DIR:FILEPATH=${MITK_PYTHON_SITE_DIR}) else() set(_vtk_install_python_dir -DVTK_INSTALL_PYTHON_MODULE_DIR:PATH=${ep_prefix}/lib/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}/site-packages) endif() list(APPEND additional_cmake_args -DVTK_WRAP_PYTHON:BOOL=ON -DVTK_USE_TK:BOOL=OFF -DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF -DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE} -DPYTHON_INCLUDE_DIR:PATH=${PYTHON_INCLUDE_DIR} -DPYTHON_INCLUDE_DIR2:PATH=${PYTHON_INCLUDE_DIR2} -DPYTHON_LIBRARY:FILEPATH=${PYTHON_LIBRARY} ${_vtk_install_python_dir} ) else() list(APPEND additional_cmake_args -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WINDOWS_PYTHON_DEBUGGABLE:BOOL=OFF ) endif() if(MITK_USE_Qt5) list(APPEND additional_cmake_args -DVTK_QT_VERSION:STRING=5 -DVTK_Group_Qt:BOOL=ON -DVTK_INSTALL_NO_QT_PLUGIN:BOOL=ON ) endif() if(CTEST_USE_LAUNCHERS) list(APPEND additional_cmake_args "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake" ) endif() - set(VTK_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/VTK-7.0.0.tar.gz) - set(VTK_URL_MD5 5fe35312db5fb2341139b8e4955c367d) + #set(VTK_URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/VTK-7.0.0.tar.gz) + set(VTK_URL http://www.vtk.org/files/release/7.1/VTK-7.1.0.tar.gz) + set(VTK_URL_MD5 a7e814c1db503d896af72458c2d0228f) ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${VTK_URL} URL_MD5 ${VTK_URL_MD5} PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/VTK.patch CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} -DVTK_WRAP_TCL:BOOL=OFF -DVTK_WRAP_PYTHON:BOOL=OFF -DVTK_WRAP_JAVA:BOOL=OFF -DVTK_USE_SYSTEM_FREETYPE:BOOL=${VTK_USE_SYSTEM_FREETYPE} -DVTK_LEGACY_REMOVE:BOOL=ON -DModule_vtkTestingRendering:BOOL=ON -DVTK_MAKE_INSTANTIATORS:BOOL=ON -DVTK_USE_CXX11_FEATURES:BOOL=ON - -DVTK_RENDERING_BACKEND:STRING=OpenGL + -DVTK_RENDERING_BACKEND:STRING=OpenGL2 ${additional_cmake_args} CMAKE_CACHE_ARGS ${ep_common_cache_args} CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} DEPENDS ${proj_DEPENDENCIES} ) set(VTK_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/CMakeExternals/VTK.patch b/CMakeExternals/VTK.patch index 26692c93c5..e69de29bb2 100644 --- a/CMakeExternals/VTK.patch +++ b/CMakeExternals/VTK.patch @@ -1,60 +0,0 @@ -diff --git a/CMake/GenerateExportHeader.cmake b/CMake/GenerateExportHeader.cmake -index ecfae31..11e7fad 100644 ---- a/CMake/GenerateExportHeader.cmake -+++ b/CMake/GenerateExportHeader.cmake -@@ -163,10 +163,10 @@ endmacro() - macro(_test_compiler_hidden_visibility) - - if(CMAKE_COMPILER_IS_GNUCXX) -- execute_process(COMMAND ${CMAKE_C_COMPILER} ARGS --version -+ execute_process(COMMAND ${CMAKE_C_COMPILER} --version - OUTPUT_VARIABLE _gcc_version_info - ERROR_VARIABLE _gcc_version_info) -- string(REGEX MATCH "[345]\\.[0-9]\\.[0-9]*" -+ string(REGEX MATCH "[3456]\\.[0-9]\\.[0-9]*" - _gcc_version "${_gcc_version_info}") - # gcc on mac just reports: "gcc (GCC) 3.3 20030304 ..." without the - # patch level, handle this here: -@@ -175,13 +175,13 @@ macro(_test_compiler_hidden_visibility) - _gcc_version "${_gcc_version_info}") - endif() - -- if(${_gcc_version} VERSION_LESS "4.2") -+ if(_gcc_version VERSION_LESS "4.2") - set(GCC_TOO_OLD TRUE) - endif() - endif() - - if(CMAKE_CXX_COMPILER_ID MATCHES "Intel") -- execute_process(COMMAND ${CMAKE_CXX_COMPILER} ARGS -V -+ execute_process(COMMAND ${CMAKE_CXX_COMPILER} -V - OUTPUT_VARIABLE _intel_version_info - ERROR_VARIABLE _intel_version_info) - string(REGEX REPLACE ".*Version ([0-9]+(\\.[0-9]+)+).*" "\\1" -diff --git a/CMake/vtkCompilerExtras.cmake b/CMake/vtkCompilerExtras.cmake -index e39bd30..68c5980 100644 ---- a/CMake/vtkCompilerExtras.cmake -+++ b/CMake/vtkCompilerExtras.cmake -@@ -28,11 +28,11 @@ if(CMAKE_COMPILER_IS_GNUCXX) - endif() - - # Now check if we can use visibility to selectively export symbols -- execute_process(COMMAND ${CMAKE_C_COMPILER} ARGS --version -+ execute_process(COMMAND ${CMAKE_C_COMPILER} --version - OUTPUT_VARIABLE _gcc_version_info - ERROR_VARIABLE _gcc_version_info) - -- string (REGEX MATCH "[345]\\.[0-9]\\.[0-9]*" -+ string (REGEX MATCH "[3456]\\.[0-9]\\.[0-9]*" - _gcc_version "${_gcc_version_info}") - if(NOT _gcc_version) - string (REGEX REPLACE ".*\\(GCC\\).*([34]\\.[0-9]).*" "\\1.0" -@@ -44,7 +44,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) - option(VTK_USE_GCC_VISIBILITY "Use GCC visibility support if available." OFF) - mark_as_advanced(VTK_USE_GCC_VISIBILITY) - -- if(${_gcc_version} VERSION_GREATER 4.2.0 AND BUILD_SHARED_LIBS -+ if(_gcc_version VERSION_GREATER 4.2.0 AND BUILD_SHARED_LIBS - AND HAVE_GCC_VISIBILITY AND VTK_USE_GCC_VISIBILITY - AND NOT MINGW AND NOT CYGWIN) - # Should only be set if GCC is newer than 4.2.0 diff --git a/Modules/Annotation/include/mitkLogoAnnotation.h b/Modules/Annotation/include/mitkLogoAnnotation.h index b0080ad9ad..13e01ae9ab 100644 --- a/Modules/Annotation/include/mitkLogoAnnotation.h +++ b/Modules/Annotation/include/mitkLogoAnnotation.h @@ -1,102 +1,110 @@ /*=================================================================== 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 LOGOAnnotation_H #define LOGOAnnotation_H #include "MitkAnnotationExports.h" #include #include #include -class mitkVtkLogoRepresentation; class vtkImageData; class vtkImageReader2Factory; class vtkImageImport; +class vtkActor2D; +class vtkImageMapper; +class vtkImageResize; namespace mitk { /** \brief Displays a logo on the renderwindow */ class MITKANNOTATION_EXPORT LogoAnnotation : public mitk::VtkAnnotation { public: class LocalStorage : public mitk::Annotation::BaseLocalStorage { public: /** \brief Actor of a 2D render window. */ vtkSmartPointer m_LogoImage; - vtkSmartPointer m_LogoRep; /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; + vtkSmartPointer m_ImageActor; + vtkSmartPointer m_ImageMapper; + vtkSmartPointer m_ImageResize; + /** \brief Default constructor of the local storage. */ LocalStorage(); /** \brief Default deconstructor of the local storage. */ ~LocalStorage(); }; mitkClassMacro(LogoAnnotation, mitk::VtkAnnotation); itkFactorylessNewMacro(Self) itkCloneMacro(Self) vtkSmartPointer m_readerFactory; void SetLogoImagePath(std::string text); std::string GetLogoImagePath() const; + + virtual Annotation::Bounds GetBoundsOnDisplay(BaseRenderer *renderer) const override; + virtual void SetBoundsOnDisplay(BaseRenderer *renderer, const Bounds &bounds) override; /** \brief The relative offset to the corner position */ void SetOffsetVector(const Point2D &OffsetVector); Point2D GetOffsetVector() const; /** \brief The corner where the logo is displayed. 0 = Bottom left 1 = Bottom right 2 = Top right 3 = Top left 4 = Center*/ void SetCornerPosition(const int &corner); int GetCornerPosition() const; void SetRelativeSize(const float &size); float GetRelativeSize() const; protected: /** \brief The LocalStorageHandler holds all LocalStorages for the render windows. */ mutable mitk::LocalStorageHandler m_LSH; virtual vtkProp *GetVtkProp(BaseRenderer *renderer) const override; void UpdateVtkAnnotation(mitk::BaseRenderer *renderer) override; vtkImageData *CreateMbiLogo(); /** \brief explicit constructor which disallows implicit conversions */ explicit LogoAnnotation(); /** \brief virtual destructor in order to derive from this class */ virtual ~LogoAnnotation(); private: vtkSmartPointer m_VtkImageImport; /** \brief copy constructor */ LogoAnnotation(const LogoAnnotation &); /** \brief assignment operator */ LogoAnnotation &operator=(const LogoAnnotation &); }; } // namespace mitk #endif // LOGOAnnotation_H diff --git a/Modules/Annotation/src/mitkLogoAnnotation.cpp b/Modules/Annotation/src/mitkLogoAnnotation.cpp index d27d5b96ba..be68ef00db 100644 --- a/Modules/Annotation/src/mitkLogoAnnotation.cpp +++ b/Modules/Annotation/src/mitkLogoAnnotation.cpp @@ -1,204 +1,279 @@ /*=================================================================== 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 "mitkLogoAnnotation.h" +#include "mitkEqual.h" #include "vtkUnicodeString.h" #include #include #include -#include #include #include #include #include #include #include +#include #include -#include +#include +#include #include #include +#include + +class vtkWindowModifiedCallback : public vtkCommand +{ +public: + static vtkWindowModifiedCallback *New() + { + return new vtkWindowModifiedCallback; + } + + mitk::LogoAnnotation::LocalStorage* ls; + double relativeSize = 0.; + + virtual void Execute(vtkObject *caller, unsigned long, void* calldata) + { + vtkRenderWindow* window = static_cast(caller); + + int dims[3]; + ls->m_LogoImage->GetDimensions(dims); + int *size = window->GetSize(); + double currentFactor = double(dims[0]) / double(size[0]); + + double desiredFactor = relativeSize; + double scaleFactor = desiredFactor / currentFactor; + + double magnificationFactor[3]; + ls->m_ImageResize->GetMagnificationFactors(magnificationFactor); + + if (!mitk::Equal(scaleFactor, magnificationFactor[0])){ + ls->m_ImageResize->SetMagnificationFactors(scaleFactor, scaleFactor, scaleFactor); + ls->m_ImageResize->Update(); + } + + /*ls->m_ImageActor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport(); + ls->m_ImageActor->GetPosition2Coordinate()->SetCoordinateSystemToNormalizedViewport(); + ls->m_ImageActor->SetPosition(0.75, 0.05);*/ + } + + vtkWindowModifiedCallback() { this->ls = 0; } +}; + mitk::LogoAnnotation::LogoAnnotation() { m_readerFactory = vtkSmartPointer::New(); mitk::Point2D offset; offset.Fill(0.03); SetOffsetVector(offset); SetRelativeSize(0.2); SetLogoImagePath("mbiLogo"); SetCornerPosition(3); m_VtkImageImport = vtkSmartPointer::New(); } mitk::LogoAnnotation::~LogoAnnotation() { for (BaseRenderer *renderer : m_LSH.GetRegisteredBaseRenderer()) { if (renderer) { this->RemoveFromBaseRenderer(renderer); } } } mitk::LogoAnnotation::LocalStorage::~LocalStorage() { } mitk::LogoAnnotation::LocalStorage::LocalStorage() { - m_LogoRep = vtkSmartPointer::New(); + m_ImageActor = vtkSmartPointer::New(); + m_ImageMapper = vtkSmartPointer::New(); + m_ImageActor->SetMapper(m_ImageMapper); + + m_ImageResize = vtkSmartPointer::New(); } void mitk::LogoAnnotation::UpdateVtkAnnotation(mitk::BaseRenderer *renderer) { LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer); if (ls->IsGenerateDataRequired(renderer, this)) { if (GetLogoImagePath().empty()) { - ls->m_LogoRep->SetVisibility(0); + ls->m_ImageActor->SetVisibility(0); return; } vtkImageReader2 *imageReader = m_readerFactory->CreateImageReader2(GetLogoImagePath().c_str()); if (imageReader) { imageReader->SetFileName(GetLogoImagePath().c_str()); imageReader->Update(); ls->m_LogoImage = imageReader->GetOutput(); imageReader->Delete(); } else { ls->m_LogoImage = CreateMbiLogo(); } + ls->m_ImageMapper->SetInputConnection(ls->m_ImageResize->GetOutputPort()); + ls->m_ImageMapper->SetColorWindow(255); + ls->m_ImageMapper->SetColorLevel(127.5); + ls->m_ImageResize->SetInputData(ls->m_LogoImage); + ls->m_ImageResize->SetResizeMethodToMagnificationFactors(); + ls->m_ImageResize->SetMagnificationFactors(1., 1., 1.); + vtkSmartPointer wCallback = vtkSmartPointer::New(); + wCallback->ls = ls; + wCallback->relativeSize = GetRelativeSize(); + + renderer->GetRenderWindow()->AddObserver(vtkCommand::ModifiedEvent, wCallback); + + float opacity; + this->GetOpacity(opacity); + ls->m_ImageActor->GetProperty()->SetOpacity(opacity); - ls->m_LogoRep->SetImage(ls->m_LogoImage); - ls->m_LogoRep->SetDragable(false); - ls->m_LogoRep->SetMoving(false); - ls->m_LogoRep->SetPickable(false); - ls->m_LogoRep->SetShowBorder(true); - ls->m_LogoRep->SetRenderer(renderer->GetVtkRenderer()); - float size = GetRelativeSize(); - ls->m_LogoRep->SetPosition2(size, size); - int corner = GetCornerPosition(); - ls->m_LogoRep->SetCornerPosition(corner); - mitk::Point2D offset = GetOffsetVector(); - ls->m_LogoRep->SetPosition(offset[0], offset[1]); - float opacity = 1.0; - GetOpacity(opacity); - ls->m_LogoRep->GetImageProperty()->SetOpacity(opacity); - ls->m_LogoRep->BuildRepresentation(); + ls->m_ImageActor->GetPositionCoordinate()->SetCoordinateSystemToDisplay(); + ls->m_ImageActor->GetPosition2Coordinate()->SetCoordinateSystemToDisplay(); ls->UpdateGenerateDataTime(); + } } vtkImageData *mitk::LogoAnnotation::CreateMbiLogo() { m_VtkImageImport->SetDataScalarTypeToUnsignedChar(); m_VtkImageImport->SetNumberOfScalarComponents(mbiLogo_NumberOfScalars); m_VtkImageImport->SetWholeExtent(0, mbiLogo_Width - 1, 0, mbiLogo_Height - 1, 0, 1 - 1); m_VtkImageImport->SetDataExtentToWholeExtent(); char *ImageData; // flip mbi logo around y axis and change color order ImageData = new char[mbiLogo_Height * mbiLogo_Width * mbiLogo_NumberOfScalars]; unsigned int column, row; char *dest = ImageData; char *source = (char *)&mbiLogo_Data[0]; ; char r, g, b, a; for (column = 0; column < mbiLogo_Height; column++) for (row = 0; row < mbiLogo_Width; row++) { // change r with b b = *source++; g = *source++; r = *source++; a = *source++; *dest++ = r; *dest++ = g; *dest++ = b; *dest++ = a; } m_VtkImageImport->SetImportVoidPointer(ImageData); m_VtkImageImport->Modified(); m_VtkImageImport->Update(); return m_VtkImageImport->GetOutput(); } void mitk::LogoAnnotation::SetLogoImagePath(std::string path) { SetStringProperty("Annotation.LogoImagePath", path.c_str()); Modified(); } std::string mitk::LogoAnnotation::GetLogoImagePath() const { std::string path; GetPropertyList()->GetStringProperty("Annotation.LogoImagePath", path); return path; } +mitk::Annotation::Bounds mitk::LogoAnnotation::GetBoundsOnDisplay(mitk::BaseRenderer *renderer) const +{ + LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer); + mitk::Annotation::Bounds bounds; + bounds.Position = ls->m_ImageActor->GetPosition(); + + int size[3]; + ls->m_ImageResize->GetOutput()->GetDimensions(size); + bounds.Size[0] = size[0]; + bounds.Size[1] = size[1]; + + return bounds; +} + +void mitk::LogoAnnotation::SetBoundsOnDisplay(mitk::BaseRenderer *renderer, const mitk::Annotation::Bounds &bounds) +{ + LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer); + + mitk::Point2D posT; + posT[0] = bounds.Position[0]; + posT[1] = bounds.Position[1]; + + ls->m_ImageActor->SetDisplayPosition(posT[0], posT[1]); +} + void mitk::LogoAnnotation::SetOffsetVector(const Point2D &OffsetVector) { mitk::Point2dProperty::Pointer OffsetVectorProperty = mitk::Point2dProperty::New(OffsetVector); SetProperty("Annotation.OffsetVector", OffsetVectorProperty.GetPointer()); Modified(); } mitk::Point2D mitk::LogoAnnotation::GetOffsetVector() const { mitk::Point2D OffsetVector; OffsetVector.Fill(0); GetPropertyValue("Annotation.OffsetVector", OffsetVector); return OffsetVector; } void mitk::LogoAnnotation::SetCornerPosition(const int &corner) { SetIntProperty("Annotation.CornerPosition", corner); Modified(); } int mitk::LogoAnnotation::GetCornerPosition() const { int corner = 0; GetIntProperty("Annotation.CornerPosition", corner); return corner; } void mitk::LogoAnnotation::SetRelativeSize(const float &size) { SetFloatProperty("Annotation.RelativeSize", size); Modified(); } float mitk::LogoAnnotation::GetRelativeSize() const { float size = 0; GetFloatProperty("Annotation.RelativeSize", size); return size; } vtkProp *mitk::LogoAnnotation::GetVtkProp(BaseRenderer *renderer) const { LocalStorage *ls = this->m_LSH.GetLocalStorage(renderer); - return ls->m_LogoRep; + + return ls->m_ImageActor; } diff --git a/Modules/Core/CMakeLists.txt b/Modules/Core/CMakeLists.txt index a20d8efb33..cfbf199126 100644 --- a/Modules/Core/CMakeLists.txt +++ b/Modules/Core/CMakeLists.txt @@ -1,77 +1,77 @@ set(TOOL_CPPS "") # temporary suppress warnings in the following files until image accessors are fully integrated. set_source_files_properties( src/DataManagement/mitkImage.cpp COMPILE_FLAGS -DMITK_NO_DEPRECATED_WARNINGS ) set_source_files_properties( src/Controllers/mitkSliceNavigationController.cpp COMPILE_FLAGS -DMITK_NO_DEPRECATED_WARNINGS ) MITK_CREATE_MODULE( INCLUDE_DIRS PUBLIC ${MITK_BINARY_DIR} PRIVATE src/Algorithms src/Controllers src/DataManagement src/Interactions src/IO src/Rendering ${OPENGL_INCLUDE_DIR} DEPENDS PUBLIC mbilog CppMicroServices PACKAGE_DEPENDS PRIVATE tinyxml OpenGL # Remove public GDCM and ITKIOGDCM+... dependencies after mitkDicomSeriesReader was removed PUBLIC GDCM PUBLIC ITK|ITKTransform+ITKImageGrid+ITKImageFeature+ITKIOImageBase+ITKIOGDCM+ITKIOHDF5+ITKIOLSM+ITKIOMRC+ITKIOBioRad+ITKIOGE+ITKIOStimulate # We privately use/link all ITK modules in order to support all IO, Transform, etc. # factories from ITK which are registered "automatically" via a factory manager. PRIVATE ITK - PUBLIC VTK|vtkFiltersTexture+vtkFiltersParallel+vtkImagingStencil+vtkImagingMath+vtkInteractionStyle+vtkRenderingOpenGL+vtkRenderingVolumeOpenGL+vtkRenderingFreeType+vtkRenderingLabel+vtkInteractionWidgets+vtkIOGeometry+vtkIOXML + PUBLIC VTK|vtkFiltersTexture+vtkFiltersParallel+vtkImagingStencil+vtkImagingMath+vtkInteractionStyle+vtkRenderingOpenGL2+vtkRenderingVolumeOpenGL2+vtkRenderingFreeType+vtkRenderingLabel+vtkInteractionWidgets+vtkIOGeometry+vtkIOXML PUBLIC Boost SUBPROJECTS MITK-Core # Do not automatically create CppMicroServices initialization code. # Because the VTK 6 "auto-init" functionality injects file-local static # initialization code in every cpp file which includes a VTK header, # static initialization order becomes an issue again. For the Mitk # core library, we need to ensure that the VTK static initialization stuff # happens before the CppMicroServices initialization, since the latter # might already use VTK code which needs to access VTK object factories. # Hence, CppMicroServices initialization code is placed manually within # the mitkCoreActivator.cpp file. NO_INIT ) if(NOT TARGET ${MODULE_TARGET}) message(SEND_ERROR "Core target ${MODULE_TARGET} does not exist") endif() function(_itk_create_factory_register_manager) # In MITK_ITK_Config.cmake, we do *not* include ITK_USE_FILE, which # prevents multiple registrations/unregistrations of ITK IO factories # during library loading/unloading (of MITK libraries). However, we need # "one" place where the IO factories are registered at # least once. This could be the application executable, but every executable would # need to take care of that itself. Instead, we allow the auto registration in the # Mitk Core library. set(NO_DIRECTORY_SCOPED_ITK_COMPILE_DEFINITION 1) find_package(ITK) include(${ITK_USE_FILE}) if(NOT ITK_NO_IO_FACTORY_REGISTER_MANAGER) # We manually add the define which will be of target scope. MITK # patches ITK_USE_FILE to remove the directory scoped compile # definition since it would be propagated to other targets in the # same directory scope but these targets might want to *not* # use the ITK factory manager stuff. target_compile_definitions(${MODULE_TARGET} PRIVATE ITK_IO_FACTORY_REGISTER_MANAGER) endif() endfunction() _itk_create_factory_register_manager() # this is needed for libraries which link to Mitk and need # symbols from explicitly instantiated templates if(MINGW) get_target_property(_mitkCore_MINGW_linkflags ${MODULE_TARGET} LINK_FLAGS) if(NOT _mitkCore_MINGW_linkflags) set(_mitkCore_MINGW_linkflags "") endif(NOT _mitkCore_MINGW_linkflags) set_target_properties(${MODULE_TARGET} PROPERTIES LINK_FLAGS "${_mitkCore_MINGW_linkflags} -Wl,--export-all-symbols") endif(MINGW) if(MSVC_IDE OR MSVC_VERSION OR MINGW) target_link_libraries(${MODULE_TARGET} PRIVATE psapi.lib) endif(MSVC_IDE OR MSVC_VERSION OR MINGW) add_subdirectory(TestingHelper) add_subdirectory(test) diff --git a/Modules/Core/TestingHelper/src/mitkRenderingTestHelper.cpp b/Modules/Core/TestingHelper/src/mitkRenderingTestHelper.cpp index d0a917b508..3bf2313050 100644 --- a/Modules/Core/TestingHelper/src/mitkRenderingTestHelper.cpp +++ b/Modules/Core/TestingHelper/src/mitkRenderingTestHelper.cpp @@ -1,308 +1,307 @@ /*=================================================================== 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 gl to read out properties #include -#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) : m_AutomaticallyCloseRenderWindow(true) { this->Initialize(width, height, renderingMode); } mitk::RenderingTestHelper::RenderingTestHelper( int width, int height, int argc, char *argv[], mitk::BaseRenderer::RenderingMode::Type 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) { 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); #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 (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/files.cmake b/Modules/Core/files.cmake index 402ddc6d26..6ff5c66759 100644 --- a/Modules/Core/files.cmake +++ b/Modules/Core/files.cmake @@ -1,314 +1,312 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkCoreActivator.cpp mitkCoreObjectFactoryBase.cpp mitkCoreObjectFactory.cpp mitkCoreServices.cpp mitkException.cpp Algorithms/mitkBaseDataSource.cpp Algorithms/mitkClippedSurfaceBoundsCalculator.cpp Algorithms/mitkCompareImageDataFilter.cpp Algorithms/mitkCompositePixelValueToString.cpp Algorithms/mitkConvert2Dto3DImageFilter.cpp Algorithms/mitkDataNodeSource.cpp Algorithms/mitkExtractSliceFilter.cpp Algorithms/mitkHistogramGenerator.cpp Algorithms/mitkImageChannelSelector.cpp Algorithms/mitkImageSliceSelector.cpp Algorithms/mitkImageSource.cpp Algorithms/mitkImageTimeSelector.cpp Algorithms/mitkImageToImageFilter.cpp Algorithms/mitkImageToSurfaceFilter.cpp Algorithms/mitkMultiComponentImageDataComparisonFilter.cpp Algorithms/mitkPlaneGeometryDataToSurfaceFilter.cpp Algorithms/mitkPointSetSource.cpp Algorithms/mitkPointSetToPointSetFilter.cpp Algorithms/mitkRGBToRGBACastImageFilter.cpp Algorithms/mitkSubImageSelector.cpp Algorithms/mitkSurfaceSource.cpp Algorithms/mitkSurfaceToImageFilter.cpp Algorithms/mitkSurfaceToSurfaceFilter.cpp Algorithms/mitkUIDGenerator.cpp Algorithms/mitkVolumeCalculator.cpp Controllers/mitkBaseController.cpp Controllers/mitkCallbackFromGUIThread.cpp Controllers/mitkCameraController.cpp Controllers/mitkCameraRotationController.cpp Controllers/mitkLimitedLinearUndo.cpp Controllers/mitkOperationEvent.cpp Controllers/mitkPlanePositionManager.cpp Controllers/mitkProgressBar.cpp Controllers/mitkRenderingManager.cpp Controllers/mitkSliceNavigationController.cpp Controllers/mitkSlicesCoordinator.cpp Controllers/mitkStatusBar.cpp Controllers/mitkStepper.cpp Controllers/mitkTestManager.cpp Controllers/mitkUndoController.cpp Controllers/mitkVerboseLimitedLinearUndo.cpp Controllers/mitkVtkLayerController.cpp DataManagement/mitkAnatomicalStructureColorPresets.cpp DataManagement/mitkArbitraryTimeGeometry.cpp DataManagement/mitkAbstractTransformGeometry.cpp DataManagement/mitkAnnotationProperty.cpp DataManagement/mitkApplicationCursor.cpp DataManagement/mitkApplyTransformMatrixOperation.cpp DataManagement/mitkBaseData.cpp DataManagement/mitkBaseGeometry.cpp DataManagement/mitkBaseProperty.cpp DataManagement/mitkChannelDescriptor.cpp DataManagement/mitkClippingProperty.cpp DataManagement/mitkColorProperty.cpp DataManagement/mitkDataNode.cpp DataManagement/mitkDataStorage.cpp DataManagement/mitkEnumerationProperty.cpp DataManagement/mitkFloatPropertyExtension.cpp DataManagement/mitkGeometry3D.cpp DataManagement/mitkGeometryData.cpp DataManagement/mitkGeometryTransformHolder.cpp DataManagement/mitkGroupTagProperty.cpp DataManagement/mitkImageAccessorBase.cpp DataManagement/mitkImageCaster.cpp DataManagement/mitkImageCastPart1.cpp DataManagement/mitkImageCastPart2.cpp DataManagement/mitkImageCastPart3.cpp DataManagement/mitkImageCastPart4.cpp DataManagement/mitkImage.cpp DataManagement/mitkImageDataItem.cpp DataManagement/mitkImageDescriptor.cpp DataManagement/mitkImageReadAccessor.cpp DataManagement/mitkImageStatisticsHolder.cpp DataManagement/mitkImageVtkAccessor.cpp DataManagement/mitkImageVtkReadAccessor.cpp DataManagement/mitkImageVtkWriteAccessor.cpp DataManagement/mitkImageWriteAccessor.cpp DataManagement/mitkIntPropertyExtension.cpp DataManagement/mitkIPersistenceService.cpp DataManagement/mitkIPropertyAliases.cpp DataManagement/mitkIPropertyDescriptions.cpp DataManagement/mitkIPropertyExtensions.cpp DataManagement/mitkIPropertyFilters.cpp DataManagement/mitkIPropertyPersistence.cpp DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjector.cpp DataManagement/mitkLevelWindow.cpp DataManagement/mitkLevelWindowManager.cpp DataManagement/mitkLevelWindowPreset.cpp DataManagement/mitkLevelWindowProperty.cpp DataManagement/mitkLine.cpp DataManagement/mitkLookupTable.cpp DataManagement/mitkLookupTableProperty.cpp DataManagement/mitkLookupTables.cpp # specializations of GenericLookupTable DataManagement/mitkMaterial.cpp DataManagement/mitkMemoryUtilities.cpp DataManagement/mitkModalityProperty.cpp DataManagement/mitkModifiedLock.cpp DataManagement/mitkNodePredicateAnd.cpp DataManagement/mitkNodePredicateBase.cpp DataManagement/mitkNodePredicateCompositeBase.cpp DataManagement/mitkNodePredicateData.cpp DataManagement/mitkNodePredicateDataType.cpp DataManagement/mitkNodePredicateDimension.cpp DataManagement/mitkNodePredicateFirstLevel.cpp DataManagement/mitkNodePredicateGeometry.cpp DataManagement/mitkNodePredicateNot.cpp DataManagement/mitkNodePredicateOr.cpp DataManagement/mitkNodePredicateProperty.cpp DataManagement/mitkNodePredicateDataProperty.cpp DataManagement/mitkNodePredicateSource.cpp DataManagement/mitkNumericConstants.cpp DataManagement/mitkPlaneGeometry.cpp DataManagement/mitkPlaneGeometryData.cpp DataManagement/mitkPlaneOperation.cpp DataManagement/mitkPlaneOrientationProperty.cpp DataManagement/mitkPointOperation.cpp DataManagement/mitkPointSet.cpp DataManagement/mitkPointSetShapeProperty.cpp DataManagement/mitkProperties.cpp DataManagement/mitkPropertyAliases.cpp DataManagement/mitkPropertyDescriptions.cpp DataManagement/mitkPropertyExtension.cpp DataManagement/mitkPropertyExtensions.cpp DataManagement/mitkPropertyFilter.cpp DataManagement/mitkPropertyFilters.cpp DataManagement/mitkPropertyList.cpp DataManagement/mitkPropertyListReplacedObserver.cpp DataManagement/mitkPropertyNameHelper.cpp DataManagement/mitkPropertyObserver.cpp DataManagement/mitkPropertyPersistence.cpp DataManagement/mitkPropertyPersistenceInfo.cpp DataManagement/mitkProportionalTimeGeometry.cpp DataManagement/mitkRenderingModeProperty.cpp DataManagement/mitkResliceMethodProperty.cpp DataManagement/mitkRestorePlanePositionOperation.cpp DataManagement/mitkRotationOperation.cpp DataManagement/mitkScaleOperation.cpp - DataManagement/mitkShaderProperty.cpp DataManagement/mitkSlicedData.cpp DataManagement/mitkSlicedGeometry3D.cpp DataManagement/mitkSmartPointerProperty.cpp DataManagement/mitkStandaloneDataStorage.cpp DataManagement/mitkStringProperty.cpp DataManagement/mitkSurface.cpp DataManagement/mitkSurfaceOperation.cpp DataManagement/mitkThinPlateSplineCurvedGeometry.cpp DataManagement/mitkTimeGeometry.cpp DataManagement/mitkTransferFunction.cpp DataManagement/mitkTransferFunctionInitializer.cpp DataManagement/mitkTransferFunctionProperty.cpp DataManagement/mitkTemporoSpatialStringProperty.cpp DataManagement/mitkVector.cpp DataManagement/mitkVectorProperty.cpp DataManagement/mitkVtkInterpolationProperty.cpp DataManagement/mitkVtkRepresentationProperty.cpp DataManagement/mitkVtkResliceInterpolationProperty.cpp DataManagement/mitkVtkScalarModeProperty.cpp DataManagement/mitkVtkVolumeRenderingProperty.cpp DataManagement/mitkWeakPointerProperty.cpp Interactions/mitkAction.cpp Interactions/mitkBindDispatcherInteractor.cpp Interactions/mitkCrosshairPositionEvent.cpp Interactions/mitkDataInteractor.cpp Interactions/mitkDispatcher.cpp Interactions/mitkDisplayCoordinateOperation.cpp Interactions/mitkDisplayInteractor.cpp Interactions/mitkEventConfig.cpp Interactions/mitkEventFactory.cpp Interactions/mitkEventRecorder.cpp Interactions/mitkEventStateMachine.cpp Interactions/mitkInteractionEventConst.cpp Interactions/mitkInteractionEvent.cpp Interactions/mitkInteractionEventHandler.cpp Interactions/mitkInteractionEventObserver.cpp Interactions/mitkInteractionKeyEvent.cpp Interactions/mitkInteractionPositionEvent.cpp Interactions/mitkInternalEvent.cpp Interactions/mitkMouseDoubleClickEvent.cpp Interactions/mitkMouseModeSwitcher.cpp Interactions/mitkMouseMoveEvent.cpp Interactions/mitkMousePressEvent.cpp Interactions/mitkMouseReleaseEvent.cpp Interactions/mitkMouseWheelEvent.cpp Interactions/mitkPointSetDataInteractor.cpp Interactions/mitkSinglePointDataInteractor.cpp Interactions/mitkStateMachineAction.cpp Interactions/mitkStateMachineCondition.cpp Interactions/mitkStateMachineContainer.cpp Interactions/mitkStateMachineState.cpp Interactions/mitkStateMachineTransition.cpp Interactions/mitkVtkEventAdapter.cpp Interactions/mitkVtkInteractorStyle.cxx Interactions/mitkXML2EventParser.cpp IO/mitkAbstractFileIO.cpp IO/mitkAbstractFileReader.cpp IO/mitkAbstractFileWriter.cpp IO/mitkCustomMimeType.cpp IO/mitkDicomSeriesReader.cpp IO/mitkDicomSeriesReaderService.cpp IO/mitkDicomSR_GantryTiltInformation.cpp IO/mitkDicomSR_ImageBlockDescriptor.cpp IO/mitkDicomSR_LoadDICOMRGBPixel4D.cpp IO/mitkDicomSR_LoadDICOMRGBPixel.cpp IO/mitkDicomSR_LoadDICOMScalar4D.cpp IO/mitkDicomSR_LoadDICOMScalar.cpp IO/mitkDicomSR_SliceGroupingResult.cpp IO/mitkFileReader.cpp IO/mitkFileReaderRegistry.cpp IO/mitkFileReaderSelector.cpp IO/mitkFileReaderWriterBase.cpp IO/mitkFileWriter.cpp IO/mitkFileWriterRegistry.cpp IO/mitkFileWriterSelector.cpp IO/mitkGeometry3DToXML.cpp IO/mitkIFileIO.cpp IO/mitkIFileReader.cpp IO/mitkIFileWriter.cpp IO/mitkGeometryDataReaderService.cpp IO/mitkGeometryDataWriterService.cpp IO/mitkImageGenerator.cpp IO/mitkImageVtkLegacyIO.cpp IO/mitkImageVtkXmlIO.cpp IO/mitkIMimeTypeProvider.cpp IO/mitkIOConstants.cpp IO/mitkIOMimeTypes.cpp IO/mitkIOUtil.cpp IO/mitkItkImageIO.cpp IO/mitkItkLoggingAdapter.cpp IO/mitkLegacyFileReaderService.cpp IO/mitkLegacyFileWriterService.cpp IO/mitkLocaleSwitch.cpp IO/mitkLog.cpp IO/mitkMimeType.cpp IO/mitkMimeTypeProvider.cpp IO/mitkOperation.cpp IO/mitkPixelType.cpp IO/mitkPointSetReaderService.cpp IO/mitkPointSetWriterService.cpp IO/mitkProportionalTimeGeometryToXML.cpp IO/mitkRawImageFileReader.cpp IO/mitkStandardFileLocations.cpp IO/mitkSurfaceStlIO.cpp IO/mitkSurfaceVtkIO.cpp IO/mitkSurfaceVtkLegacyIO.cpp IO/mitkSurfaceVtkXmlIO.cpp IO/mitkVtkLoggingAdapter.cpp IO/mitkPreferenceListReaderOptionsFunctor.cpp Rendering/mitkAbstractAnnotationRenderer.cpp Rendering/mitkAnnotationUtils.cpp Rendering/mitkBaseRenderer.cpp #Rendering/mitkGLMapper.cpp Moved to deprecated LegacyGL Module Rendering/mitkGradientBackground.cpp Rendering/mitkImageVtkMapper2D.cpp - Rendering/mitkIShaderRepository.cpp Rendering/mitkMapper.cpp Rendering/mitkAnnotation.cpp Rendering/mitkPlaneGeometryDataMapper2D.cpp Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp Rendering/mitkPointSetVtkMapper2D.cpp Rendering/mitkPointSetVtkMapper3D.cpp Rendering/mitkRenderWindowBase.cpp Rendering/mitkRenderWindow.cpp Rendering/mitkRenderWindowFrame.cpp #Rendering/mitkSurfaceGLMapper2D.cpp Moved to deprecated LegacyGL Module Rendering/mitkSurfaceVtkMapper2D.cpp Rendering/mitkSurfaceVtkMapper3D.cpp Rendering/mitkVtkEventProvider.cpp Rendering/mitkVtkMapper.cpp Rendering/mitkVtkPropRenderer.cpp Rendering/mitkVtkWidgetRendering.cpp Rendering/vtkMitkLevelWindowFilter.cpp Rendering/vtkMitkRectangleProp.cpp Rendering/vtkMitkRenderProp.cpp Rendering/vtkMitkThickSlicesFilter.cpp Rendering/vtkNeverTranslucentTexture.cpp ) set(RESOURCE_FILES Interactions/globalConfig.xml Interactions/DisplayInteraction.xml Interactions/DisplayConfig.xml Interactions/DisplayConfigPACS.xml Interactions/DisplayConfigPACSPan.xml Interactions/DisplayConfigPACSScroll.xml Interactions/DisplayConfigPACSZoom.xml Interactions/DisplayConfigPACSLevelWindow.xml Interactions/DisplayConfigMITK.xml Interactions/DisplayConfigMITKNoCrosshair.xml Interactions/DisplayConfigMITKRotation.xml Interactions/DisplayConfigMITKRotationUnCoupled.xml Interactions/DisplayConfigMITKSwivel.xml Interactions/DisplayConfigMITKLimited.xml Interactions/PointSet.xml Interactions/Legacy/StateMachine.xml Interactions/Legacy/DisplayConfigMITKTools.xml Interactions/PointSetConfig.xml mitkLevelWindowPresets.xml mitkAnatomicalStructureColorPresets.xml ) diff --git a/Modules/Core/include/mitkCoreServices.h b/Modules/Core/include/mitkCoreServices.h index cc91558851..d47043e871 100644 --- a/Modules/Core/include/mitkCoreServices.h +++ b/Modules/Core/include/mitkCoreServices.h @@ -1,173 +1,166 @@ /*=================================================================== 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 MITKCORESERVICES_H #define MITKCORESERVICES_H #include "MitkCoreExports.h" #include #include #include #include #include #include #include namespace mitk { struct IMimeTypeProvider; - struct IShaderRepository; class IPropertyAliases; class IPropertyDescriptions; class IPropertyExtensions; class IPropertyFilters; class IPropertyPersistence; /** * @brief Access MITK core services. * * This class can be used to conveniently access common * MITK Core service objects. Some getter methods where implementations * exist in the core library are guaranteed to return a non-nullptr service object. * * To ensure that CoreServices::Unget() is called after the caller * has finished using a service object, you should use the CoreServicePointer * helper class which calls Unget() when it goes out of scope: * * \code * CoreServicePointer shaderRepo(CoreServices::GetShaderRepository()); * // Do something with shaderRepo * \endcode * * @see CoreServicePointer */ class MITKCORE_EXPORT CoreServices { public: - /** - * @brief Get an IShaderRepository instance. - * @param context The module context of the module getting the service. - * @return A IShaderRepository instance which can be nullptr. - */ - static IShaderRepository *GetShaderRepository(); /** * @brief Get an IPropertyAliases instance. * @param context The module context of the module getting the service. * @return A non-nullptr IPropertyAliases instance. */ static IPropertyAliases *GetPropertyAliases(us::ModuleContext *context = us::GetModuleContext()); /** * @brief Get an IPropertyDescriptions instance. * @param context The module context of the module getting the service. * @return A non-nullptr IPropertyDescriptions instance. */ static IPropertyDescriptions *GetPropertyDescriptions(us::ModuleContext *context = us::GetModuleContext()); /** * @brief Get an IPropertyExtensions instance. * @param context The module context of the module getting the service. * @return A non-nullptr IPropertyExtensions instance. */ static IPropertyExtensions *GetPropertyExtensions(us::ModuleContext *context = us::GetModuleContext()); /** * @brief Get an IPropertyFilters instance. * @param context The module context of the module getting the service. * @return A non-nullptr IPropertyFilters instance. */ static IPropertyFilters *GetPropertyFilters(us::ModuleContext *context = us::GetModuleContext()); /** * @brief Get an IPropertyPersistence instance. * @param context The module context of the module getting the service. * @return A non-nullptr IPropertyPersistence instance. */ static IPropertyPersistence *GetPropertyPersistence(us::ModuleContext *context = us::GetModuleContext()); /** * @brief Get an IMimeTypeProvider instance. * @param context The module context of the module getting the service. * @return A non-nullptr IMimeTypeProvider instance. */ static IMimeTypeProvider *GetMimeTypeProvider(us::ModuleContext *context = us::GetModuleContext()); /** * @brief Unget a previously acquired service instance. * @param service The service instance to be released. * @return \c true if ungetting the service was successful, \c false otherwise. */ template static bool Unget(S *service, us::ModuleContext *context = us::GetModuleContext()) { return Unget(context, us_service_interface_iid(), service); } private: static bool Unget(us::ModuleContext *context, const std::string &interfaceId, void *service); // purposely not implemented CoreServices(); CoreServices(const CoreServices &); CoreServices &operator=(const CoreServices &); }; /** * @brief A RAII helper class for core service objects. * * This is class is intended for usage in local scopes; it calls * CoreServices::Unget(S*) in its destructor. You should not construct * multiple CoreServicePointer instances using the same service pointer, * unless it is retrieved by a new call to a CoreServices getter method. * * @see CoreServices */ template class MITK_LOCAL CoreServicePointer { public: explicit CoreServicePointer(S *service) : m_service(service) { assert(m_service); } ~CoreServicePointer() { try { CoreServices::Unget(m_service); } catch (const std::exception &e) { MITK_ERROR << e.what(); } catch (...) { MITK_ERROR << "Ungetting core service failed."; } } S *operator->() const { return m_service; } private: // purposely not implemented CoreServicePointer(const CoreServicePointer &); CoreServicePointer &operator=(const CoreServicePointer &); S *const m_service; }; } #endif // MITKCORESERVICES_H diff --git a/Modules/Core/include/mitkIShaderRepository.h b/Modules/Core/include/mitkIShaderRepository.h deleted file mode 100644 index 749e4adb91..0000000000 --- a/Modules/Core/include/mitkIShaderRepository.h +++ /dev/null @@ -1,136 +0,0 @@ -/*=================================================================== - -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 MITKISHADERREPOSITORY_H -#define MITKISHADERREPOSITORY_H - -#include - -#include "mitkCommon.h" -#include "mitkServiceInterface.h" - -#include - -class vtkActor; -class vtkShaderProgram2; - -namespace mitk -{ - class DataNode; - class BaseRenderer; - - /** - * \ingroup MicroServices_Interfaces - * \brief Management class for vtkShader XML descriptions. - * - * Loads XML shader files from std::istream objects and adds default properties - * for each shader object (shader uniforms) to the specified mitk::DataNode. - * - * Additionally, it provides a utility function for applying properties for shaders - * in mappers. - */ - struct MITKCORE_EXPORT IShaderRepository - { - struct ShaderPrivate; - - class MITKCORE_EXPORT Shader : public itk::LightObject - { - public: - mitkClassMacroItkParent(Shader, itk::LightObject) itkFactorylessNewMacro(Self) - - ~Shader(); - - int GetId() const; - std::string GetName() const; - std::string GetMaterialXml() const; - - protected: - Shader(); - - void SetId(int id); - void SetName(const std::string &name); - void SetMaterialXml(const std::string &xml); - - private: - // not implemented - Shader(const Shader &); - Shader &operator=(const Shader &); - - ShaderPrivate *d; - }; - - class MITKCORE_EXPORT ShaderProgram : public itk::LightObject - { - public: - virtual void Activate() = 0; - virtual void Deactivate() = 0; - mitkClassMacroItkParent(ShaderProgram, itk::LightObject) - }; - - virtual ~IShaderRepository(); - - virtual std::list GetShaders() const = 0; - - /** - * \brief Return the named shader. - * - * \param name The shader name. - * \return A Shader object. - * - * Names might not be unique. Use the shader id to uniquely identify a shader. - */ - virtual Shader::Pointer GetShader(const std::string &name) const = 0; - - virtual ShaderProgram::Pointer CreateShaderProgram() = 0; - - /** - * \brief Return the shader identified by the given id. - * @param id The shader id. - * @return The shader object or null if the id is unknown. - */ - virtual Shader::Pointer GetShader(int id) const = 0; - - /** \brief Adds all parsed shader uniforms to property list of the given DataNode; - * used by mappers. - */ - virtual void AddDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) const = 0; - - /** \brief Applies shader and shader specific variables of the specified DataNode - * to the VTK object by updating the shader variables of its vtkProperty. - */ - virtual void UpdateShaderProgram(mitk::IShaderRepository::ShaderProgram *shaderProgram, - mitk::DataNode *node, - mitk::BaseRenderer *renderer) const = 0; - - /** \brief Loads a shader from a given file. Make sure that this stream is in the XML shader format. - * - * \return A unique id for the loaded shader which can be used to unload it. - */ - virtual int LoadShader(std::istream &stream, const std::string &name) = 0; - - /** - * \brief Unload a previously loaded shader. - * \param id The unique shader id returned by LoadShader. - * \return \c true if the shader id was found and the shader was successfully unloaded, - * \c false otherwise. - */ - virtual bool UnloadShader(int id) = 0; - }; -} - -MITK_DECLARE_SERVICE_INTERFACE(mitk::IShaderRepository, "org.mitk.services.IShaderRepository/1.0") - -#endif // MITKISHADERREPOSITORY_H diff --git a/Modules/Core/include/mitkPlaneClipping.h b/Modules/Core/include/mitkPlaneClipping.h index 0500a22f35..3f9748922b 100644 --- a/Modules/Core/include/mitkPlaneClipping.h +++ b/Modules/Core/include/mitkPlaneClipping.h @@ -1,154 +1,155 @@ /*=================================================================== 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 MITKPLANECLIPPING_H_HEADER_INCLUDED #define MITKPLANECLIPPING_H_HEADER_INCLUDED #include #include #include +#include #include namespace mitk { namespace PlaneClipping { /** \brief Internal helper method for intersection testing used only in CalculateClippedPlaneBounds() */ static bool LineIntersectZero(vtkPoints *points, int p1, int p2, double *bounds) { double point1[3]; double point2[3]; points->GetPoint(p1, point1); points->GetPoint(p2, point2); if ((point1[2] * point2[2] <= 0.0) && (point1[2] != point2[2])) { double x, y; x = (point1[0] * point2[2] - point1[2] * point2[0]) / (point2[2] - point1[2]); y = (point1[1] * point2[2] - point1[2] * point2[1]) / (point2[2] - point1[2]); if (x < bounds[0]) { bounds[0] = x; } if (x > bounds[1]) { bounds[1] = x; } if (y < bounds[2]) { bounds[2] = y; } if (y > bounds[3]) { bounds[3] = y; } bounds[4] = bounds[5] = 0.0; return true; } return false; } /** \brief Calculate the bounding box of the resliced image. This is necessary for arbitrarily rotated planes in an image volume. A rotated plane (e.g. in swivel mode) will have a new bounding box, which needs to be calculated. */ static bool CalculateClippedPlaneBounds(const BaseGeometry *boundingGeometry, const PlaneGeometry *planeGeometry, double *bounds) { // Clip the plane with the bounding geometry. To do so, the corner points // of the bounding box are transformed by the inverse transformation // matrix, and the transformed bounding box edges derived therefrom are // clipped with the plane z=0. The resulting min/max values are taken as // bounds for the image reslicer. const mitk::BoundingBox *boundingBox = boundingGeometry->GetBoundingBox(); mitk::BoundingBox::PointType bbMin = boundingBox->GetMinimum(); mitk::BoundingBox::PointType bbMax = boundingBox->GetMaximum(); vtkSmartPointer points = vtkSmartPointer::New(); if (boundingGeometry->GetImageGeometry()) { points->InsertPoint(0, bbMin[0] - 0.5, bbMin[1] - 0.5, bbMin[2] - 0.5); points->InsertPoint(1, bbMin[0] - 0.5, bbMin[1] - 0.5, bbMax[2] - 0.5); points->InsertPoint(2, bbMin[0] - 0.5, bbMax[1] - 0.5, bbMax[2] - 0.5); points->InsertPoint(3, bbMin[0] - 0.5, bbMax[1] - 0.5, bbMin[2] - 0.5); points->InsertPoint(4, bbMax[0] - 0.5, bbMin[1] - 0.5, bbMin[2] - 0.5); points->InsertPoint(5, bbMax[0] - 0.5, bbMin[1] - 0.5, bbMax[2] - 0.5); points->InsertPoint(6, bbMax[0] - 0.5, bbMax[1] - 0.5, bbMax[2] - 0.5); points->InsertPoint(7, bbMax[0] - 0.5, bbMax[1] - 0.5, bbMin[2] - 0.5); } else { points->InsertPoint(0, bbMin[0], bbMin[1], bbMin[2]); points->InsertPoint(1, bbMin[0], bbMin[1], bbMax[2]); points->InsertPoint(2, bbMin[0], bbMax[1], bbMax[2]); points->InsertPoint(3, bbMin[0], bbMax[1], bbMin[2]); points->InsertPoint(4, bbMax[0], bbMin[1], bbMin[2]); points->InsertPoint(5, bbMax[0], bbMin[1], bbMax[2]); points->InsertPoint(6, bbMax[0], bbMax[1], bbMax[2]); points->InsertPoint(7, bbMax[0], bbMax[1], bbMin[2]); } vtkSmartPointer newPoints = vtkSmartPointer::New(); vtkSmartPointer transform = vtkSmartPointer::New(); transform->Identity(); transform->Concatenate(planeGeometry->GetVtkTransform()->GetLinearInverse()); transform->Concatenate(boundingGeometry->GetVtkTransform()); transform->TransformPoints(points, newPoints); bounds[0] = bounds[2] = 10000000.0; bounds[1] = bounds[3] = -10000000.0; bounds[4] = bounds[5] = 0.0; LineIntersectZero(newPoints, 0, 1, bounds); LineIntersectZero(newPoints, 1, 2, bounds); LineIntersectZero(newPoints, 2, 3, bounds); LineIntersectZero(newPoints, 3, 0, bounds); LineIntersectZero(newPoints, 0, 4, bounds); LineIntersectZero(newPoints, 1, 5, bounds); LineIntersectZero(newPoints, 2, 6, bounds); LineIntersectZero(newPoints, 3, 7, bounds); LineIntersectZero(newPoints, 4, 5, bounds); LineIntersectZero(newPoints, 5, 6, bounds); LineIntersectZero(newPoints, 6, 7, bounds); LineIntersectZero(newPoints, 7, 4, bounds); if ((bounds[0] > 9999999.0) || (bounds[2] > 9999999.0) || (bounds[1] < -9999999.0) || (bounds[3] < -9999999.0)) { return false; } else { // The resulting bounds must be adjusted by the plane spacing, since we // we have so far dealt with index coordinates const mitk::Vector3D planeSpacing = planeGeometry->GetSpacing(); bounds[0] *= planeSpacing[0]; bounds[1] *= planeSpacing[0]; bounds[2] *= planeSpacing[1]; bounds[3] *= planeSpacing[1]; bounds[4] *= planeSpacing[2]; bounds[5] *= planeSpacing[2]; return true; } } } } #endif diff --git a/Modules/Core/include/mitkShaderProperty.h b/Modules/Core/include/mitkShaderProperty.h deleted file mode 100644 index 0d82ee1d2f..0000000000 --- a/Modules/Core/include/mitkShaderProperty.h +++ /dev/null @@ -1,111 +0,0 @@ -/*=================================================================== - -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 __MITKSHADERENUMPROPERTY_H -#define __MITKSHADERENUMPROPERTY_H - -#include "mitkEnumerationProperty.h" - -namespace mitk -{ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4522) -#endif - - /** - * Encapsulates the shader enumeration - */ - class MITKCORE_EXPORT ShaderProperty : public EnumerationProperty - { - public: - class Element - { - public: - std::string name; - }; - - mitkClassMacro(ShaderProperty, EnumerationProperty); - - itkFactorylessNewMacro(Self) itkCloneMacro(Self) - - mitkNewMacro1Param(ShaderProperty, const IdType &); - - mitkNewMacro1Param(ShaderProperty, const std::string &); - - /** - * Returns the current scalar mode value as defined by VTK constants. - * @returns the current scalar mode as VTK constant. - */ - IdType GetShaderId(); - std::string GetShaderName(); - void SetShader(const IdType &i); - void SetShader(const std::string &i); - - using BaseProperty::operator=; - - protected: - std::list shaderList; - - /** - * Constructor. Sets the representation to a default value of surface(2) - */ - ShaderProperty(); - - ShaderProperty(const ShaderProperty &other); - - /** - * \brief Sets the scalar mode to the given value. If it is not - * valid, the scalar mode is set to default (0). - * @param value the integer representation of the scalar mode - */ - ShaderProperty(const IdType &value); - - /** - * \brief Sets the scalar mode to the given value. If it is not - * valid, the representation is set to default (0). - * @param value the string representation of the scalar mode - */ - ShaderProperty(const std::string &value); - - /** - * this function is overridden as protected, so that the user may not add - * additional invalid scalar mode types. - */ - bool AddEnum(const std::string &name, const IdType &id = 0) override; - - /** - * Adds the enumeration types as defined by vtk to the list of known - * enumeration values. - */ - void AddShaderTypes(); - - private: - // purposely not implemented - ShaderProperty &operator=(const ShaderProperty &); - - virtual itk::LightObject::Pointer InternalClone() const override; - - virtual bool Assign(const BaseProperty &property) override; - }; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -} // end of namespace mitk - -#endif //_MITK_VTK_SCALARMODE_PROPERTY__H_ diff --git a/Modules/Core/include/mitkSurfaceVtkMapper3D.h b/Modules/Core/include/mitkSurfaceVtkMapper3D.h index 57f3ca187c..cecdab1456 100644 --- a/Modules/Core/include/mitkSurfaceVtkMapper3D.h +++ b/Modules/Core/include/mitkSurfaceVtkMapper3D.h @@ -1,148 +1,147 @@ /*=================================================================== 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 mitkSurfaceVtkMapper3D_h #define mitkSurfaceVtkMapper3D_h #include "mitkBaseRenderer.h" #include "mitkLocalStorageHandler.h" #include "mitkVtkMapper.h" #include #include #include #include -#include #include #include #include #include namespace mitk { /** * @brief Vtk-based mapper for Surfaces. * * The mapper renders a surface in 3D. The actor is adapted according to the geometry in * the base class in mitk::VtkMapper::UpdateVtkTransform(). * * Properties that can be set for surfaces and influence the surfaceVTKMapper3D are: * * - \b "Backface Culling": True enables backface culling, which means only front-facing polygons will be visualized. False/disabled by default. * - \b "color": (ColorProperty) Diffuse color of the surface object (this property will be read when material.diffuseColor is not defined) * - \b "Opacity": (FloatProperty) Opacity of the surface object * - \b "material.ambientColor": (ColorProperty) Ambient color of the surface object * - \b "material.ambientCoefficient": ( FloatProperty) Ambient coefficient of the surface object * - \b "material.diffuseColor": ( ColorProperty) Diffuse color of the surface object * - \b "material.diffuseCoefficient": (FloatProperty) Diffuse coefficient of the surface object * - \b "material.specularColor": (ColorProperty) Specular Color of the surface object * - \b "material.specularCoefficient": (FloatProperty) Specular coefficient of the surface object * - \b "material.specularPower": (FloatProperty) Specular power of the surface object * - \b "material.interpolation": (VtkInterpolationProperty) Interpolation * - \b "material.representation": (VtkRepresentationProperty*) Representation * - \b "material.wireframeLineWidth": (FloatProperty) Width in pixels of the lines drawn. * - \b "material.pointSize": (FloatProperty) Size in pixels of the points drawn. * - \b "scalar visibility": (BoolProperty) If the scarlars of the surface are visible * - \b "Surface.TransferFunction (TransferFunctionProperty) Set a transferfunction for coloring the surface * - \b "LookupTable (LookupTableProperty) LookupTable * Properties to look for are: * * - \b "scalar visibility": if set to on, scalars assigned to the data are shown * Turn this on if using a lookup table. * - \b "ScalarsRangeMinimum": Optional. Can be used to store the scalar min, e.g. * for the level window settings. * - \b "ScalarsRangeMaximum": Optional. See above. * * There might be still some other, deprecated properties. These will not be documented anymore. * Please check the source if you really need them. * * @ingroup Mapper */ class MITKCORE_EXPORT SurfaceVtkMapper3D : public VtkMapper { public: mitkClassMacro(SurfaceVtkMapper3D, VtkMapper); itkFactorylessNewMacro(Self) itkCloneMacro(Self) itkSetMacro(GenerateNormals, bool); itkGetMacro(GenerateNormals, bool); virtual const mitk::Surface *GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer) override; virtual void ApplyAllProperties(mitk::BaseRenderer *renderer, vtkActor *actor); static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer = nullptr, bool overwrite = false); protected: SurfaceVtkMapper3D(); virtual ~SurfaceVtkMapper3D(); virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override; virtual void ResetMapper(mitk::BaseRenderer *renderer) override; /** Checks whether the specified property is a ClippingProperty and if yes, * adds it to m_ClippingPlaneCollection (internal method). */ virtual void CheckForClippingProperty(mitk::BaseRenderer *renderer, mitk::BaseProperty *property); bool m_GenerateNormals; public: class LocalStorage : public mitk::Mapper::BaseLocalStorage { public: vtkSmartPointer m_Actor; - vtkSmartPointer m_VtkPolyDataMapper; + vtkSmartPointer m_VtkPolyDataMapper; vtkSmartPointer m_VtkPolyDataNormals; vtkSmartPointer m_ClippingPlaneCollection; vtkSmartPointer m_DepthSort; itk::TimeStamp m_ShaderTimestampUpdate; LocalStorage() { - m_VtkPolyDataMapper = vtkSmartPointer::New(); + m_VtkPolyDataMapper = vtkSmartPointer::New(); m_VtkPolyDataNormals = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); m_ClippingPlaneCollection = vtkSmartPointer::New(); m_Actor->SetMapper(m_VtkPolyDataMapper); m_DepthSort = vtkSmartPointer::New(); } ~LocalStorage() {} }; mitk::LocalStorageHandler m_LSH; static void ApplyMitkPropertiesToVtkProperty(mitk::DataNode *node, vtkProperty *property, mitk::BaseRenderer *renderer); static void SetDefaultPropertiesForVtkProperty(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite); }; } // namespace mitk #endif /* mitkSurfaceVtkMapper3D_h */ diff --git a/Modules/Core/include/mitkVtkMapper.h b/Modules/Core/include/mitkVtkMapper.h index 15cd86b0d3..7d494b662d 100644 --- a/Modules/Core/include/mitkVtkMapper.h +++ b/Modules/Core/include/mitkVtkMapper.h @@ -1,177 +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. ===================================================================*/ // change number #ifndef VTKMAPPER_H_HEADER_INCLUDED_C1C5453B #define VTKMAPPER_H_HEADER_INCLUDED_C1C5453B #include "mitkBaseRenderer.h" #include "mitkDataNode.h" -#include "mitkIShaderRepository.h" #include "mitkLocalStorageHandler.h" #include "mitkMapper.h" #include "mitkVtkPropRenderer.h" #include #include #include #include #include #include #include #include #include #include class vtkProp; class vtkProp3D; class vtkActor; namespace mitk { /** \brief Base class of all Vtk Mappers in order to display primitives * by exploiting Vtk functionality. * * Rendering of opaque, translucent or volumetric geometry and overlays * is done in consecutive render passes. * * \ingroup Mapper */ class MITKCORE_EXPORT VtkMapper : public Mapper { public: mitkClassMacro(VtkMapper, Mapper); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer) = 0; /** \brief Re-issues all drawing commands required to describe * the entire scene each time a new frame is required, * regardless of actual changes. */ static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); /** * \brief Returns whether this is an vtk-based mapper * \deprecatedSince{2013_03} All mappers of superclass VTKMapper are vtk based, use a dynamic_cast instead */ DEPRECATED(virtual bool IsVtkBased() const override); /** \brief Determines which geometry should be rendered * (opaque, translucent, volumetric, overlay) * and calls the appropriate function. * * Called by mitk::VtkPropRenderer::Render */ void MitkRender(mitk::BaseRenderer *renderer, mitk::VtkPropRenderer::RenderType type) override; /** \brief Checks visibility and renders the overlay */ virtual void MitkRenderOverlay(BaseRenderer *renderer); /** \brief Checks visibility and renders untransparent geometry */ virtual void MitkRenderOpaqueGeometry(BaseRenderer *renderer); /** \brief Checks visiblity and renders transparent geometry */ virtual void MitkRenderTranslucentGeometry(BaseRenderer *renderer); /** \brief Checks visibility and renders volumes */ virtual void MitkRenderVolumetricGeometry(BaseRenderer *renderer); /** \brief Returns true if this mapper owns the specified vtkProp for * the given BaseRenderer. * * Note: returns false by default; should be implemented for VTK-based * Mapper subclasses. */ virtual bool HasVtkProp(const vtkProp *prop, BaseRenderer *renderer); /** \brief Set the vtkTransform of the m_Prop3D for * the current time step of \a renderer * * Called by mitk::VtkPropRenderer::Update before rendering. This * method will transform all actors (e.g. of an vtkAssembly) according * the geometry. * * \warning This method transforms only props which derive * from vtkProp3D. Make sure to use vtkAssembly, if you have * multiple props. vtkPropAssembly does not work, since it derives * from vtkProp. */ virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer); /** * \brief Apply color and opacity properties read from the PropertyList * \deprecatedSince{2013_03} Use ApplyColorAndOpacityProperties(mitk::BaseRenderer* renderer, vtkActor * actor) * instead */ DEPRECATED(inline virtual void ApplyProperties(vtkActor *actor, mitk::BaseRenderer *renderer)) { ApplyColorAndOpacityProperties(renderer, actor); } /** * \brief SHADERTODO */ - void ApplyShaderProperties(mitk::BaseRenderer *renderer); + void ApplyShaderProperties(mitk::BaseRenderer *); /** * \brief Apply color and opacity properties read from the PropertyList. * Called by mapper subclasses. */ virtual void ApplyColorAndOpacityProperties(mitk::BaseRenderer *renderer, vtkActor *actor) override; /** * \brief Release vtk-based graphics resources that are being consumed by this mapper. * * Method called by mitk::VtkPropRenderer. The parameter renderer could be used to * determine which graphic resources to release. The local storage is accessible * by the parameter renderer. Should be overwritten in subclasses. */ virtual void ReleaseGraphicsResources(mitk::BaseRenderer * /*renderer*/) {} class VtkMapperLocalStorage : public mitk::Mapper::BaseLocalStorage { public: - mitk::IShaderRepository::ShaderProgram::Pointer m_ShaderProgram; itk::TimeStamp m_ModifiedTimeStamp; VtkMapperLocalStorage() { - IShaderRepository *shaderRepo = CoreServices::GetShaderRepository(); - if (shaderRepo) - { - m_ShaderProgram = shaderRepo->CreateShaderProgram(); - } } ~VtkMapperLocalStorage() {} }; mitk::LocalStorageHandler m_VtkMapperLSH; protected: /** constructor */ VtkMapper(); /** virtual destructor in order to derive from this class */ virtual ~VtkMapper(); private: /** copy constructor */ VtkMapper(const VtkMapper &); /** assignment operator */ VtkMapper &operator=(const VtkMapper &); }; } // namespace mitk #endif /* VTKMAPPER_H_HEADER_INCLUDED_C1C5453B */ diff --git a/Modules/Core/include/vtkMitkLevelWindowFilter.h b/Modules/Core/include/vtkMitkLevelWindowFilter.h index d78365ad98..b9dffd22d7 100644 --- a/Modules/Core/include/vtkMitkLevelWindowFilter.h +++ b/Modules/Core/include/vtkMitkLevelWindowFilter.h @@ -1,102 +1,102 @@ /*=================================================================== 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 __vtkMitkLevelWindowFilter_h #define __vtkMitkLevelWindowFilter_h class vtkScalarsToColors; class vtkPiecewiseFunction; #include #include #include /** Documentation * \brief Applies the grayvalue or color/opacity level window to scalar or RGB(A) images. * * This filter is used to apply the color level window to RGB images (e.g. * diffusion tensor images). Therefore, the RGB channels are converted to * the HSI color space, where the level window can be applied. Afterwards, * the HSI values transformed back to the RGB space. * * The filter is also able to apply an opacity level window to RGBA images. * * \ingroup Renderer */ class MITKCORE_EXPORT vtkMitkLevelWindowFilter : public vtkThreadedImageAlgorithm { public: vtkTypeMacro(vtkMitkLevelWindowFilter, vtkThreadedImageAlgorithm); static vtkMitkLevelWindowFilter *New(); - virtual unsigned long int GetMTime() override; + virtual vtkMTimeType GetMTime() override; /** \brief Get the lookup table for the RGB level window */ vtkScalarsToColors *GetLookupTable(); /** \brief Set the lookup table for the RGB level window */ void SetLookupTable(vtkScalarsToColors *lookupTable); /** \brief Get the piecewise function used to map scalar to alpha component value (only * used when the lookupTable is a vtkColorTransferFunction) */ vtkPiecewiseFunction *GetOpacityPiecewiseFunction() { return m_OpacityFunction; } /** \brief Set the piecewise function used to map scalar to alpha component value (only * used when the lookupTable is a vtkColorTransferFunction) */ void SetOpacityPiecewiseFunction(vtkPiecewiseFunction *opacityFunction); /** \brief Get/Set the lower window opacity for the alpha level window */ void SetMinOpacity(double minOpacity); inline double GetMinOpacity() const; /** \brief Get/Set the upper window opacity for the alpha level window */ void SetMaxOpacity(double maxOpacity); inline double GetMaxOpacity() const; /** \brief Set clipping bounds for the opaque part of the resliced 2d image */ void SetClippingBounds(double *); protected: /** Default constructor. */ vtkMitkLevelWindowFilter(); /** Default deconstructor. */ ~vtkMitkLevelWindowFilter(); /** \brief Method for threaded execution of the filter. * \param *inData: The input. * \param *outData: The output of the filter. * \param extent: Specifies the region of the image to be updated inside this thread. * It is a six-component array of the form (xmin, xmax, ymin, ymax, zmin, zmax). * \param id: The thread id. */ void ThreadedExecute(vtkImageData *inData, vtkImageData *outData, int extent[6], int id) override; // /** Standard VTK filter method to apply the filter. See VTK documentation.*/ int RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override; // /** Standard VTK filter method to apply the filter. See VTK documentation. Not used at the moment.*/ // void ExecuteInformation(vtkImageData *vtkNotUsed(inData), vtkImageData *vtkNotUsed(outData)); private: /** m_LookupTable contains the lookup table for the RGB level window.*/ vtkScalarsToColors *m_LookupTable; /** The transfer function to map the scalar to alpha (4th component of the RGBA output value) */ vtkPiecewiseFunction *m_OpacityFunction; /** m_MinOpacity contains the lower bound for the alpha level window.*/ double m_MinOpacity; /** m_MaxOpacity contains the upper bound for the alpha level window.*/ double m_MaxOpacity; double m_ClippingBounds[4]; }; #endif diff --git a/Modules/Core/include/vtkNeverTranslucentTexture.h b/Modules/Core/include/vtkNeverTranslucentTexture.h index fcfc29addf..5a62b4aa58 100644 --- a/Modules/Core/include/vtkNeverTranslucentTexture.h +++ b/Modules/Core/include/vtkNeverTranslucentTexture.h @@ -1,102 +1,102 @@ /*=================================================================== 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 mitkNeverTranslucentTexture_h #define mitkNeverTranslucentTexture_h #include #include #include /** \brief VTK Fix to speed up our image rendering. The way we render images while changing the contrast via level/window extremely slows down rendering. The cause of this slowdown is that VTK asks a texture (via a call to IsTranslucent) if it is translucent. When the texture refers to a lookup table this question is answered in a most expensive way: pushing every pixel through the lookup table to see whether it would render translucent. We can speed this up extremely by always answering NO. 2D Image rendering in the context of MITK is still correct. This class is injected into the VTK system by registering it with vtkObjectFactory as a replacement for vtkTexture. We chose vtkOpenGLTexture as super class, because it seems that the other texture super class is deprecated: http://www.cmake.org/Wiki/VTK:How_I_mangled_Mesa \sa ImageVtkMapper2D */ /* NOT exported, this is a 2D image mapper helper */ class MITKCORE_EXPORT vtkNeverTranslucentTexture : public vtkOpenGLTexture { public: static vtkNeverTranslucentTexture *New(); - vtkTypeMacro(vtkNeverTranslucentTexture, vtkTexture); + vtkTypeMacro(vtkNeverTranslucentTexture, vtkOpenGLTexture); void PrintSelf(ostream &os, vtkIndent indent) override; /** \brief The FIX (see class description). VTK Description: Is this Texture Translucent? Returns false (0) if the texture is either fully opaque or has only fully transparent pixels and fully opaque pixels and the Interpolate flag is turn off. */ virtual int IsTranslucent() override; protected: vtkNeverTranslucentTexture(); private: vtkNeverTranslucentTexture(const vtkNeverTranslucentTexture &); // Not implemented. void operator=(const vtkNeverTranslucentTexture &); // Not implemented. }; /** \brief Factory for vtkNeverTranslucentTexture (see this class!). Registered in CoreActivator to replace all instances of vtkTexture with vtkNeverTranslucentTexture. Required to make rendering of images during level/window operations acceptably fast. */ class vtkNeverTranslucentTextureFactory : public vtkObjectFactory { public: vtkNeverTranslucentTextureFactory(); static vtkNeverTranslucentTextureFactory *New(); virtual const char *GetVTKSourceVersion() override; const char *GetDescription() override; protected: vtkNeverTranslucentTextureFactory(const vtkNeverTranslucentTextureFactory &); void operator=(const vtkNeverTranslucentTextureFactory &); }; #endif diff --git a/Modules/Core/src/Rendering/mitkIShaderRepository.cpp b/Modules/Core/src/Rendering/mitkIShaderRepository.cpp deleted file mode 100644 index 7e9e8b92ff..0000000000 --- a/Modules/Core/src/Rendering/mitkIShaderRepository.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/*=================================================================== - -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 "mitkIShaderRepository.h" - -namespace mitk -{ - IShaderRepository::~IShaderRepository() {} - struct IShaderRepository::ShaderPrivate - { - ShaderPrivate() : id(-1) {} - int id; - std::string name; - std::string materialXml; - }; - - IShaderRepository::Shader::Shader() : d(new ShaderPrivate) {} - void IShaderRepository::Shader::SetId(int id) { d->id = id; } - IShaderRepository::Shader::~Shader() { delete d; } - int IShaderRepository::Shader::GetId() const { return d->id; } - std::string IShaderRepository::Shader::GetName() const { return d->name; } - std::string IShaderRepository::Shader::GetMaterialXml() const { return d->materialXml; } - void IShaderRepository::Shader::SetName(const std::string &name) { d->name = name; } - void IShaderRepository::Shader::SetMaterialXml(const std::string &xml) { d->materialXml = xml; } -} diff --git a/Modules/Core/src/Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp b/Modules/Core/src/Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp index 0e5a82b349..ac25920ae4 100644 --- a/Modules/Core/src/Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp +++ b/Modules/Core/src/Rendering/mitkPlaneGeometryDataVtkMapper3D.cpp @@ -1,589 +1,589 @@ /*=================================================================== 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 "mitkPlaneGeometryDataVtkMapper3D.h" #include "mitkImageVtkMapper2D.h" #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateOr.h" #include "mitkSmartPointerProperty.h" #include "mitkSurface.h" #include "mitkVtkRepresentationProperty.h" #include "mitkWeakPointerProperty.h" #include "vtkMitkLevelWindowFilter.h" #include "vtkNeverTranslucentTexture.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace mitk { PlaneGeometryDataVtkMapper3D::PlaneGeometryDataVtkMapper3D() : m_NormalsActorAdded(false), m_DataStorage(nullptr) { m_EdgeTuber = vtkTubeFilter::New(); m_EdgeMapper = vtkPolyDataMapper::New(); m_SurfaceCreator = PlaneGeometryDataToSurfaceFilter::New(); m_SurfaceCreatorBoundingBox = BoundingBox::New(); m_SurfaceCreatorPointsContainer = BoundingBox::PointsContainer::New(); m_Edges = vtkFeatureEdges::New(); m_Edges->BoundaryEdgesOn(); m_Edges->FeatureEdgesOff(); m_Edges->NonManifoldEdgesOff(); m_Edges->ManifoldEdgesOff(); m_EdgeTransformer = vtkTransformPolyDataFilter::New(); m_NormalsTransformer = vtkTransformPolyDataFilter::New(); m_EdgeActor = vtkActor::New(); m_BackgroundMapper = vtkPolyDataMapper::New(); m_BackgroundActor = vtkActor::New(); m_Prop3DAssembly = vtkAssembly::New(); m_ImageAssembly = vtkAssembly::New(); m_SurfaceCreatorBoundingBox->SetPoints(m_SurfaceCreatorPointsContainer); m_Cleaner = vtkCleanPolyData::New(); m_Cleaner->PieceInvariantOn(); m_Cleaner->ConvertLinesToPointsOn(); m_Cleaner->ConvertPolysToLinesOn(); m_Cleaner->ConvertStripsToPolysOn(); m_Cleaner->PointMergingOn(); // Make sure that the FeatureEdge algorithm is initialized with a "valid" // (though empty) input vtkPolyData *emptyPolyData = vtkPolyData::New(); m_Cleaner->SetInputData(emptyPolyData); emptyPolyData->Delete(); m_Edges->SetInputConnection(m_Cleaner->GetOutputPort()); m_EdgeTransformer->SetInputConnection(m_Edges->GetOutputPort()); m_EdgeTuber->SetInputConnection(m_EdgeTransformer->GetOutputPort()); m_EdgeTuber->SetVaryRadiusToVaryRadiusOff(); m_EdgeTuber->SetNumberOfSides(12); m_EdgeTuber->CappingOn(); m_EdgeMapper->SetInputConnection(m_EdgeTuber->GetOutputPort()); m_EdgeMapper->ScalarVisibilityOff(); m_BackgroundMapper->SetInputData(emptyPolyData); m_BackgroundMapper->Update(); m_EdgeActor->SetMapper(m_EdgeMapper); m_BackgroundActor->GetProperty()->SetAmbient(0.5); m_BackgroundActor->GetProperty()->SetColor(0.0, 0.0, 0.0); m_BackgroundActor->GetProperty()->SetOpacity(0.0); m_BackgroundActor->SetMapper(m_BackgroundMapper); vtkProperty *backfaceProperty = m_BackgroundActor->MakeProperty(); backfaceProperty->SetColor(0.0, 0.0, 0.0); m_BackgroundActor->SetBackfaceProperty(backfaceProperty); backfaceProperty->Delete(); m_FrontHedgeHog = vtkHedgeHog::New(); m_BackHedgeHog = vtkHedgeHog::New(); m_FrontNormalsMapper = vtkPolyDataMapper::New(); m_FrontNormalsMapper->SetInputConnection(m_FrontHedgeHog->GetOutputPort()); m_BackNormalsMapper = vtkPolyDataMapper::New(); m_Prop3DAssembly->AddPart(m_EdgeActor); m_Prop3DAssembly->AddPart(m_ImageAssembly); m_FrontNormalsActor = vtkActor::New(); m_FrontNormalsActor->SetMapper(m_FrontNormalsMapper); m_BackNormalsActor = vtkActor::New(); m_BackNormalsActor->SetMapper(m_BackNormalsMapper); m_ImageMapperDeletedCommand = MemberCommandType::New(); m_ImageMapperDeletedCommand->SetCallbackFunction(this, &PlaneGeometryDataVtkMapper3D::ImageMapperDeletedCallback); } PlaneGeometryDataVtkMapper3D::~PlaneGeometryDataVtkMapper3D() { m_ImageAssembly->Delete(); m_Prop3DAssembly->Delete(); m_EdgeTuber->Delete(); m_EdgeMapper->Delete(); m_EdgeTransformer->Delete(); m_Cleaner->Delete(); m_Edges->Delete(); m_NormalsTransformer->Delete(); m_EdgeActor->Delete(); m_BackgroundMapper->Delete(); m_BackgroundActor->Delete(); m_FrontNormalsMapper->Delete(); m_FrontNormalsActor->Delete(); m_FrontHedgeHog->Delete(); m_BackNormalsMapper->Delete(); m_BackNormalsActor->Delete(); m_BackHedgeHog->Delete(); for (ActorList::iterator it = m_ImageActors.begin(); it != m_ImageActors.end(); ++it) it->second.m_Actor->ReleaseGraphicsResources(0); // Delete entries in m_ImageActors list one by one m_ImageActors.clear(); m_DataStorage = nullptr; } vtkProp *PlaneGeometryDataVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) { if ((this->GetDataNode() != nullptr) && (m_ImageAssembly != nullptr)) { // Do not transform the entire Prop3D assembly, but only the image part // here. The colored frame is transformed elsewhere (via m_EdgeTransformer), // since only vertices should be transformed there, not the poly data // itself, to avoid distortion for anisotropic datasets. m_ImageAssembly->SetUserTransform(this->GetDataNode()->GetVtkTransform()); } return m_Prop3DAssembly; } void PlaneGeometryDataVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) { m_ImageAssembly->SetUserTransform(this->GetDataNode()->GetVtkTransform(this->GetTimestep())); } const PlaneGeometryData *PlaneGeometryDataVtkMapper3D::GetInput() { return static_cast(GetDataNode()->GetData()); } void PlaneGeometryDataVtkMapper3D::SetDataStorageForTexture(mitk::DataStorage *storage) { if (storage != nullptr && m_DataStorage != storage) { m_DataStorage = storage; this->Modified(); } } void PlaneGeometryDataVtkMapper3D::ImageMapperDeletedCallback(itk::Object *caller, const itk::EventObject & /*event*/) { ImageVtkMapper2D *imageMapper = dynamic_cast(caller); if ((imageMapper != nullptr)) { if (m_ImageActors.count(imageMapper) > 0) { m_ImageActors[imageMapper].m_Sender = nullptr; // sender is already destroying itself m_ImageActors.erase(imageMapper); } } } void PlaneGeometryDataVtkMapper3D::GenerateDataForRenderer(BaseRenderer *renderer) { SetVtkMapperImmediateModeRendering(m_EdgeMapper); SetVtkMapperImmediateModeRendering(m_BackgroundMapper); // Remove all actors from the assembly, and re-initialize it with the // edge actor m_ImageAssembly->GetParts()->RemoveAllItems(); bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if (!visible) { // visibility has explicitly to be set in the single actors // due to problems when using cell picking: // even if the assembly is invisible, the renderer contains // references to the assemblies parts. During picking the // visibility of each part is checked, and not only for the // whole assembly. m_ImageAssembly->VisibilityOff(); m_EdgeActor->VisibilityOff(); return; } // visibility has explicitly to be set in the single actors // due to problems when using cell picking: // even if the assembly is invisible, the renderer contains // references to the assemblies parts. During picking the // visibility of each part is checked, and not only for the // whole assembly. m_ImageAssembly->VisibilityOn(); bool drawEdges = true; this->GetDataNode()->GetBoolProperty("draw edges", drawEdges, renderer); m_EdgeActor->SetVisibility(drawEdges); PlaneGeometryData::Pointer input = const_cast(this->GetInput()); if (input.IsNotNull() && (input->GetPlaneGeometry() != nullptr)) { SmartPointerProperty::Pointer surfacecreatorprop; surfacecreatorprop = dynamic_cast(GetDataNode()->GetProperty("surfacegeometry", renderer)); if ((surfacecreatorprop.IsNull()) || (surfacecreatorprop->GetSmartPointer().IsNull()) || ((m_SurfaceCreator = dynamic_cast(surfacecreatorprop->GetSmartPointer().GetPointer())) .IsNull())) { m_SurfaceCreator->PlaceByGeometryOn(); surfacecreatorprop = SmartPointerProperty::New(m_SurfaceCreator); GetDataNode()->SetProperty("surfacegeometry", surfacecreatorprop); } m_SurfaceCreator->SetInput(input); int res; if (GetDataNode()->GetIntProperty("xresolution", res, renderer)) { m_SurfaceCreator->SetXResolution(res); } if (GetDataNode()->GetIntProperty("yresolution", res, renderer)) { m_SurfaceCreator->SetYResolution(res); } double tubeRadius = 1.0; // Radius of tubular edge surrounding plane // Clip the PlaneGeometry with the reference geometry bounds (if available) if (input->GetPlaneGeometry()->HasReferenceGeometry()) { const BaseGeometry *referenceGeometry = input->GetPlaneGeometry()->GetReferenceGeometry(); BoundingBox::PointType boundingBoxMin, boundingBoxMax; boundingBoxMin = referenceGeometry->GetBoundingBox()->GetMinimum(); boundingBoxMax = referenceGeometry->GetBoundingBox()->GetMaximum(); if (referenceGeometry->GetImageGeometry()) { for (unsigned int i = 0; i < 3; ++i) { boundingBoxMin[i] -= 0.5; boundingBoxMax[i] -= 0.5; } } m_SurfaceCreatorPointsContainer->CreateElementAt(0) = boundingBoxMin; m_SurfaceCreatorPointsContainer->CreateElementAt(1) = boundingBoxMax; m_SurfaceCreatorBoundingBox->ComputeBoundingBox(); m_SurfaceCreator->SetBoundingBox(m_SurfaceCreatorBoundingBox); tubeRadius = referenceGeometry->GetDiagonalLength() / 450.0; } // If no reference geometry is available, clip with the current global // bounds else if (m_DataStorage.IsNotNull()) { m_SurfaceCreator->SetBoundingBox(m_DataStorage->ComputeVisibleBoundingBox(nullptr, "includeInBoundingBox")); tubeRadius = sqrt(m_SurfaceCreator->GetBoundingBox()->GetDiagonalLength2()) / 450.0; } // Calculate the surface of the PlaneGeometry m_SurfaceCreator->Update(); Surface *surface = m_SurfaceCreator->GetOutput(); // Check if there's something to display, otherwise return if ((surface->GetVtkPolyData() == 0) || (surface->GetVtkPolyData()->GetNumberOfCells() == 0)) { m_ImageAssembly->VisibilityOff(); return; } // add a graphical representation of the surface normals if requested DataNode *node = this->GetDataNode(); bool displayNormals = false; bool colorTwoSides = false; bool invertNormals = false; node->GetBoolProperty("draw normals 3D", displayNormals, renderer); node->GetBoolProperty("color two sides", colorTwoSides, renderer); node->GetBoolProperty("invert normals", invertNormals, renderer); // if we want to draw the display normals or render two sides we have to get the colors if (displayNormals || colorTwoSides) { // get colors float frontColor[3] = {0.0, 0.0, 1.0}; node->GetColor(frontColor, renderer, "front color"); float backColor[3] = {1.0, 0.0, 0.0}; node->GetColor(backColor, renderer, "back color"); if (displayNormals) { m_NormalsTransformer->SetInputData(surface->GetVtkPolyData()); m_NormalsTransformer->SetTransform(node->GetVtkTransform(this->GetTimestep())); m_FrontHedgeHog->SetInputConnection(m_NormalsTransformer->GetOutputPort()); m_FrontHedgeHog->SetVectorModeToUseNormal(); m_FrontHedgeHog->SetScaleFactor(invertNormals ? 1.0 : -1.0); m_FrontHedgeHog->Update(); m_FrontNormalsActor->GetProperty()->SetColor(frontColor[0], frontColor[1], frontColor[2]); m_BackHedgeHog->SetInputConnection(m_NormalsTransformer->GetOutputPort()); m_BackHedgeHog->SetVectorModeToUseNormal(); m_BackHedgeHog->SetScaleFactor(invertNormals ? -1.0 : 1.0); m_BackHedgeHog->Update(); m_BackNormalsActor->GetProperty()->SetColor(backColor[0], backColor[1], backColor[2]); // if there is no actor added yet, add one if (!m_NormalsActorAdded) { m_Prop3DAssembly->AddPart(m_FrontNormalsActor); m_Prop3DAssembly->AddPart(m_BackNormalsActor); m_NormalsActorAdded = true; } } // if we don't want to display normals AND there is an actor added remove the actor else if (m_NormalsActorAdded) { m_Prop3DAssembly->RemovePart(m_FrontNormalsActor); m_Prop3DAssembly->RemovePart(m_BackNormalsActor); m_NormalsActorAdded = false; } if (colorTwoSides) { if (!invertNormals) { m_BackgroundActor->GetProperty()->SetColor(backColor[0], backColor[1], backColor[2]); m_BackgroundActor->GetBackfaceProperty()->SetColor(frontColor[0], frontColor[1], frontColor[2]); } else { m_BackgroundActor->GetProperty()->SetColor(frontColor[0], frontColor[1], frontColor[2]); m_BackgroundActor->GetBackfaceProperty()->SetColor(backColor[0], backColor[1], backColor[2]); } } } // Add black background for all images (which may be transparent) m_BackgroundMapper->SetInputData(surface->GetVtkPolyData()); - m_ImageAssembly->AddPart(m_BackgroundActor); + // m_ImageAssembly->AddPart(m_BackgroundActor); LayerSortedActorList layerSortedActors; // Traverse the data tree to find nodes resliced by ImageMapperGL2D // use a predicate to get all data nodes which are "images" or inherit from mitk::Image mitk::TNodePredicateDataType::Pointer predicateAllImages = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetSubset(predicateAllImages); // process all found images for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { DataNode *node = it->Value(); if (node != nullptr) this->ProcessNode(node, renderer, surface, layerSortedActors); } // Add all image actors to the assembly, sorted according to // layer property LayerSortedActorList::iterator actorIt; for (actorIt = layerSortedActors.begin(); actorIt != layerSortedActors.end(); ++actorIt) { m_ImageAssembly->AddPart(actorIt->second); } // Configurate the tube-shaped frame: size according to the surface // bounds, color as specified in the plane's properties vtkPolyData *surfacePolyData = surface->GetVtkPolyData(); m_Cleaner->SetInputData(surfacePolyData); m_EdgeTransformer->SetTransform(this->GetDataNode()->GetVtkTransform(this->GetTimestep())); // Adjust the radius according to extent m_EdgeTuber->SetRadius(tubeRadius); // Get the plane's color and set the tube properties accordingly ColorProperty::Pointer colorProperty; colorProperty = dynamic_cast(this->GetDataNode()->GetProperty("color")); if (colorProperty.IsNotNull()) { const Color &color = colorProperty->GetColor(); m_EdgeActor->GetProperty()->SetColor(color.GetRed(), color.GetGreen(), color.GetBlue()); } else { m_EdgeActor->GetProperty()->SetColor(1.0, 1.0, 1.0); } m_ImageAssembly->SetUserTransform(this->GetDataNode()->GetVtkTransform(this->GetTimestep())); } VtkRepresentationProperty *representationProperty; this->GetDataNode()->GetProperty(representationProperty, "material.representation", renderer); if (representationProperty != nullptr) m_BackgroundActor->GetProperty()->SetRepresentation(representationProperty->GetVtkRepresentation()); } void PlaneGeometryDataVtkMapper3D::ProcessNode(DataNode *node, BaseRenderer *renderer, Surface *surface, LayerSortedActorList &layerSortedActors) { if (node != nullptr) { // we need to get the information from the 2D mapper to render the texture on the 3D plane ImageVtkMapper2D *imageMapper = dynamic_cast(node->GetMapper(1)); // GetMapper(1) provides the 2D mapper for the data node // if there is a 2D mapper, which is not the standard image mapper... if (!imageMapper && node->GetMapper(1)) { //... check if it is the composite mapper std::string cname(node->GetMapper(1)->GetNameOfClass()); if (!cname.compare("CompositeMapper")) // string.compare returns 0 if the two strings are equal. { // get the standard image mapper. // This is a special case in MITK and does only work for the CompositeMapper. imageMapper = dynamic_cast(node->GetMapper(3)); } } if ((node->IsVisible(renderer)) && imageMapper) { WeakPointerProperty::Pointer rendererProp = dynamic_cast(GetDataNode()->GetPropertyList()->GetProperty("renderer")); if (rendererProp.IsNotNull()) { BaseRenderer::Pointer planeRenderer = dynamic_cast(rendererProp->GetWeakPointer().GetPointer()); // Retrieve and update image to be mapped const ImageVtkMapper2D::LocalStorage *localStorage = imageMapper->GetLocalStorage(planeRenderer); if (planeRenderer.IsNotNull()) { // perform update of imagemapper if needed (maybe the respective 2D renderwindow is not rendered/update // before) imageMapper->Update(planeRenderer); // If it has not been initialized already in a previous pass, // generate an actor and a texture object to // render the image associated with the ImageVtkMapper2D. vtkActor *imageActor; vtkDataSetMapper *dataSetMapper = nullptr; vtkTexture *texture; if (m_ImageActors.count(imageMapper) == 0) { dataSetMapper = vtkDataSetMapper::New(); // Enable rendering without copying the image. dataSetMapper->ImmediateModeRenderingOn(); texture = vtkNeverTranslucentTexture::New(); texture->RepeatOff(); imageActor = vtkActor::New(); imageActor->SetMapper(dataSetMapper); imageActor->SetTexture(texture); imageActor->GetProperty()->SetOpacity( 0.999); // HACK! otherwise VTK wouldn't recognize this as translucent // surface (if LUT values map to alpha < 255 // improvement: apply "opacity" property onle HERE and also in 2D image mapper. DO NOT change LUT to // achieve // translucent images (see method ChangeOpacity in image mapper 2D) // Make imageActor the sole owner of the mapper and texture // objects dataSetMapper->UnRegister(nullptr); texture->UnRegister(nullptr); // Store the actor so that it may be accessed in following // passes. m_ImageActors[imageMapper].Initialize(imageActor, imageMapper, m_ImageMapperDeletedCommand); } else { // Else, retrieve the actor and associated objects from the // previous pass. imageActor = m_ImageActors[imageMapper].m_Actor; dataSetMapper = (vtkDataSetMapper *)imageActor->GetMapper(); texture = imageActor->GetTexture(); } // Set poly data new each time its object changes (e.g. when // switching between planar and curved geometries) if ((dataSetMapper != nullptr) && (dataSetMapper->GetInput() != surface->GetVtkPolyData())) { dataSetMapper->SetInputData(surface->GetVtkPolyData()); } dataSetMapper->Update(); // Check if the m_ReslicedImage is nullptr. // This is the case when no image geometry is met by // the reslicer. In that case, the texture has to be // empty (black) and we don't have to do anything. // See fixed bug #13275 if (localStorage->m_ReslicedImage != nullptr) { texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort()); // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter) texture->MapColorScalarsThroughLookupTableOff(); // re-use properties from the 2D image mapper imageActor->SetProperty(localStorage->m_Actor->GetProperty()); imageActor->GetProperty()->SetAmbient(0.5); // Set texture interpolation on/off bool textureInterpolation = node->IsOn("texture interpolation", renderer); texture->SetInterpolate(textureInterpolation); // Store this actor to be added to the actor assembly, sort // by layer int layer = 1; node->GetIntProperty("layer", layer); layerSortedActors.insert(std::pair(layer, imageActor)); } } } } } } void PlaneGeometryDataVtkMapper3D::ActorInfo::Initialize(vtkActor *actor, itk::Object *sender, itk::Command *command) { m_Actor = actor; m_Sender = sender; // Get informed when ImageMapper object is deleted, so that // the data structures built here can be deleted as well m_ObserverID = sender->AddObserver(itk::DeleteEvent(), command); } PlaneGeometryDataVtkMapper3D::ActorInfo::ActorInfo() : m_Actor(nullptr), m_Sender(nullptr), m_ObserverID(0) {} PlaneGeometryDataVtkMapper3D::ActorInfo::~ActorInfo() { if (m_Sender != nullptr) { m_Sender->RemoveObserver(m_ObserverID); } if (m_Actor != nullptr) { m_Actor->ReleaseGraphicsResources(0); m_Actor->Delete(); } } } // namespace mitk diff --git a/Modules/Core/src/Rendering/mitkPointSetVtkMapper3D.cpp b/Modules/Core/src/Rendering/mitkPointSetVtkMapper3D.cpp index a4988d204d..9259fd473c 100644 --- a/Modules/Core/src/Rendering/mitkPointSetVtkMapper3D.cpp +++ b/Modules/Core/src/Rendering/mitkPointSetVtkMapper3D.cpp @@ -1,706 +1,705 @@ /*=================================================================== 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 "mitkPointSetVtkMapper3D.h" #include "mitkColorProperty.h" #include "mitkDataNode.h" #include "mitkPointSet.h" #include "mitkProperties.h" #include "mitkVtkPropRenderer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include - #include +#include const mitk::PointSet *mitk::PointSetVtkMapper3D::GetInput() { return static_cast(GetDataNode()->GetData()); } mitk::PointSetVtkMapper3D::PointSetVtkMapper3D() : m_vtkSelectedPointList(nullptr), m_vtkUnselectedPointList(nullptr), m_VtkSelectedPolyDataMapper(nullptr), m_VtkUnselectedPolyDataMapper(nullptr), m_vtkTextList(nullptr), m_NumberOfSelectedAdded(0), m_NumberOfUnselectedAdded(0), m_PointSize(1.0), m_ContourRadius(0.5), m_VertexRendering(false) { // propassembly m_PointsAssembly = vtkSmartPointer::New(); // creating actors to be able to set transform m_SelectedActor = vtkSmartPointer::New(); m_UnselectedActor = vtkSmartPointer::New(); m_ContourActor = vtkSmartPointer::New(); } mitk::PointSetVtkMapper3D::~PointSetVtkMapper3D() { } void mitk::PointSetVtkMapper3D::ReleaseGraphicsResources(vtkWindow *renWin) { m_PointsAssembly->ReleaseGraphicsResources(renWin); m_SelectedActor->ReleaseGraphicsResources(renWin); m_UnselectedActor->ReleaseGraphicsResources(renWin); m_ContourActor->ReleaseGraphicsResources(renWin); } void mitk::PointSetVtkMapper3D::ReleaseGraphicsResources(mitk::BaseRenderer *renderer) { m_PointsAssembly->ReleaseGraphicsResources(renderer->GetRenderWindow()); m_SelectedActor->ReleaseGraphicsResources(renderer->GetRenderWindow()); m_UnselectedActor->ReleaseGraphicsResources(renderer->GetRenderWindow()); m_ContourActor->ReleaseGraphicsResources(renderer->GetRenderWindow()); } void mitk::PointSetVtkMapper3D::CreateVTKRenderObjects() { m_vtkSelectedPointList = vtkSmartPointer::New(); m_vtkUnselectedPointList = vtkSmartPointer::New(); m_PointsAssembly->VisibilityOn(); if (m_PointsAssembly->GetParts()->IsItemPresent(m_SelectedActor)) m_PointsAssembly->RemovePart(m_SelectedActor); if (m_PointsAssembly->GetParts()->IsItemPresent(m_UnselectedActor)) m_PointsAssembly->RemovePart(m_UnselectedActor); if (m_PointsAssembly->GetParts()->IsItemPresent(m_ContourActor)) m_PointsAssembly->RemovePart(m_ContourActor); // exceptional displaying for PositionTracker -> MouseOrientationTool int mapperID; bool isInputDevice = false; if (this->GetDataNode()->GetBoolProperty("inputdevice", isInputDevice) && isInputDevice) { if (this->GetDataNode()->GetIntProperty("BaseRendererMapperID", mapperID) && mapperID == BaseRenderer::Standard3D) return; // The event for the PositionTracker came from the 3d widget and not needs to be displayed } // get and update the PointSet mitk::PointSet::Pointer input = const_cast(this->GetInput()); /* only update the input data, if the property tells us to */ bool update = true; this->GetDataNode()->GetBoolProperty("updateDataOnRender", update); if (update == true) input->Update(); int timestep = this->GetTimestep(); mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet(timestep); if (itkPointSet.GetPointer() == nullptr) { m_PointsAssembly->VisibilityOff(); return; } // now fill selected and unselected pointList // get size of Points in Property m_PointSize = 2; mitk::FloatProperty::Pointer pointSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("pointsize")); if (pointSizeProp.IsNotNull()) m_PointSize = pointSizeProp->GetValue(); // get the property for creating a label onto every point only once bool showLabel = true; this->GetDataNode()->GetBoolProperty("show label", showLabel); const char *pointLabel = nullptr; if (showLabel) { if (dynamic_cast(this->GetDataNode()->GetPropertyList()->GetProperty("label")) != nullptr) pointLabel = dynamic_cast(this->GetDataNode()->GetPropertyList()->GetProperty("label"))->GetValue(); else showLabel = false; } // whether or not to creat a "contour" - connecting lines between all the points int nbPoints = itkPointSet->GetPointData()->Size(); bool makeContour = false; this->GetDataNode()->GetBoolProperty("show contour", makeContour); bool closeContour = false; this->GetDataNode()->GetBoolProperty("close contour", closeContour); int contourPointLimit = 0; // NO contour if (makeContour) { if (closeContour) contourPointLimit = nbPoints; else contourPointLimit = nbPoints - 1; } // build list of all positions for later transform in one go mitk::PointSet::PointsContainer::Iterator pointsIter; int ptIdx; m_NumberOfSelectedAdded = 0; m_NumberOfUnselectedAdded = 0; vtkSmartPointer localPoints = vtkSmartPointer::New(); m_WorldPositions = vtkSmartPointer::New(); m_PointConnections = vtkSmartPointer::New(); // m_PointConnections between points for (ptIdx = 0, pointsIter = itkPointSet->GetPoints()->Begin(); pointsIter != itkPointSet->GetPoints()->End(); pointsIter++, ptIdx++) { itk::Point currentPoint = pointsIter->Value(); localPoints->InsertPoint(ptIdx, currentPoint[0], currentPoint[1], currentPoint[2]); if (makeContour && ptIdx < contourPointLimit) { vtkIdType cell[2] = {(ptIdx + 1) % nbPoints, ptIdx}; m_PointConnections->InsertNextCell(2, cell); } } vtkSmartPointer vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); vtktransform->TransformPoints(localPoints, m_WorldPositions); // create contour if (makeContour) { this->CreateContour(m_WorldPositions, m_PointConnections); } // check if the list for the PointDataContainer is the same size as the PointsContainer. Is not, then the points were // inserted manually and can not be visualized according to the PointData (selected/unselected) bool pointDataBroken = (itkPointSet->GetPointData()->Size() != itkPointSet->GetPoints()->Size()); // now add an object for each point in data mitk::PointSet::PointDataContainer::Iterator pointDataIter = itkPointSet->GetPointData()->Begin(); for (ptIdx = 0; ptIdx < nbPoints; ++ptIdx) // pointDataIter moved at end of loop { double currentPoint[3]; m_WorldPositions->GetPoint(ptIdx, currentPoint); vtkSmartPointer source; // check for the pointtype in data and decide which geom-object to take and then add to the selected or unselected // list int pointType; if (itkPointSet->GetPointData()->size() == 0 || pointDataBroken) pointType = mitk::PTUNDEFINED; else pointType = pointDataIter.Value().pointSpec; switch (pointType) { case mitk::PTUNDEFINED: { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(m_PointSize / 2.0f); sphere->SetCenter(currentPoint); // sphere->SetCenter(pointsIter.Value()[0],pointsIter.Value()[1],pointsIter.Value()[2]); // MouseOrientation Tool (PositionTracker) if (isInputDevice) { sphere->SetThetaResolution(10); sphere->SetPhiResolution(10); } else { sphere->SetThetaResolution(20); sphere->SetPhiResolution(20); } source = sphere; } break; case mitk::PTSTART: { vtkSmartPointer cube = vtkSmartPointer::New(); cube->SetXLength(m_PointSize / 2); cube->SetYLength(m_PointSize / 2); cube->SetZLength(m_PointSize / 2); cube->SetCenter(currentPoint); source = cube; } break; case mitk::PTCORNER: { vtkSmartPointer cone = vtkSmartPointer::New(); cone->SetRadius(m_PointSize / 2.0f); cone->SetCenter(currentPoint); cone->SetResolution(20); source = cone; } break; case mitk::PTEDGE: { vtkSmartPointer cylinder = vtkSmartPointer::New(); cylinder->SetRadius(m_PointSize / 2.0f); cylinder->SetCenter(currentPoint); cylinder->SetResolution(20); source = cylinder; } break; case mitk::PTEND: { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(m_PointSize / 2.0f); // no SetCenter?? this functionality should be explained! // otherwise: join with default block! sphere->SetThetaResolution(20); sphere->SetPhiResolution(20); source = sphere; } break; default: { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(m_PointSize / 2.0f); sphere->SetCenter(currentPoint); sphere->SetThetaResolution(20); sphere->SetPhiResolution(20); source = sphere; } break; } if (pointDataIter.Value().selected && !pointDataBroken) { m_vtkSelectedPointList->AddInputConnection(source->GetOutputPort()); ++m_NumberOfSelectedAdded; } else { m_vtkUnselectedPointList->AddInputConnection(source->GetOutputPort()); ++m_NumberOfUnselectedAdded; } if (showLabel) { char buffer[20]; std::string l = pointLabel; if (input->GetSize() > 1) { sprintf(buffer, "%d", ptIdx + 1); l.append(buffer); } // Define the text for the label vtkSmartPointer label = vtkSmartPointer::New(); label->SetText(l.c_str()); //# Set up a transform to move the label to a new position. vtkSmartPointer aLabelTransform = vtkSmartPointer::New(); aLabelTransform->Identity(); aLabelTransform->Translate(currentPoint[0] + 2, currentPoint[1] + 2, currentPoint[2]); aLabelTransform->Scale(5.7, 5.7, 5.7); //# Move the label to a new position. vtkSmartPointer labelTransform = vtkSmartPointer::New(); labelTransform->SetTransform(aLabelTransform); labelTransform->SetInputConnection(label->GetOutputPort()); // add it to the wright PointList if (pointType) { m_vtkSelectedPointList->AddInputConnection(labelTransform->GetOutputPort()); ++m_NumberOfSelectedAdded; } else { m_vtkUnselectedPointList->AddInputConnection(labelTransform->GetOutputPort()); ++m_NumberOfUnselectedAdded; } } if (pointDataIter != itkPointSet->GetPointData()->End()) pointDataIter++; } // end FOR // now according to number of elements added to selected or unselected, build up the rendering pipeline if (m_NumberOfSelectedAdded > 0) { m_VtkSelectedPolyDataMapper = vtkSmartPointer::New(); m_VtkSelectedPolyDataMapper->SetInputConnection(m_vtkSelectedPointList->GetOutputPort()); // create a new instance of the actor m_SelectedActor = vtkSmartPointer::New(); m_SelectedActor->SetMapper(m_VtkSelectedPolyDataMapper); m_PointsAssembly->AddPart(m_SelectedActor); } if (m_NumberOfUnselectedAdded > 0) { m_VtkUnselectedPolyDataMapper = vtkSmartPointer::New(); m_VtkUnselectedPolyDataMapper->SetInputConnection(m_vtkUnselectedPointList->GetOutputPort()); // create a new instance of the actor m_UnselectedActor = vtkSmartPointer::New(); m_UnselectedActor->SetMapper(m_VtkUnselectedPolyDataMapper); m_PointsAssembly->AddPart(m_UnselectedActor); } } void mitk::PointSetVtkMapper3D::VertexRendering() { // get and update the PointSet mitk::PointSet::Pointer input = const_cast(this->GetInput()); /* only update the input data, if the property tells us to */ bool update = true; this->GetDataNode()->GetBoolProperty("updateDataOnRender", update); if (update == true) input->Update(); int timestep = this->GetTimestep(); mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet(timestep); // turn off standard actors m_UnselectedActor->VisibilityOff(); m_SelectedActor->VisibilityOff(); // point size m_PointSize = 2.0; mitk::FloatProperty::Pointer pointSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("pointsize")); if (pointSizeProp.IsNotNull()) m_PointSize = pointSizeProp->GetValue(); double *color = m_UnselectedActor->GetProperty()->GetColor(); double opacity = m_UnselectedActor->GetProperty()->GetOpacity(); glClearColor(0.0, 0.0, 0.0, 0.0); glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); glEnable(GL_POINT_SMOOTH); glPointSize(m_PointSize); glBegin(GL_POINTS); glColor4d(color[0], color[1], color[2], opacity); for (auto pointsIter = itkPointSet->GetPoints()->Begin(); pointsIter != itkPointSet->GetPoints()->End(); pointsIter++) { const itk::Point &point = pointsIter->Value(); glVertex3d(point[0], point[1], point[2]); } glEnd(); // reset context glPointSize(1.0); glDisable(GL_POINT_SMOOTH); glEnable(GL_COLOR_MATERIAL); glEnable(GL_LIGHTING); } void mitk::PointSetVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if (!visible) { m_UnselectedActor->VisibilityOff(); m_SelectedActor->VisibilityOff(); m_ContourActor->VisibilityOff(); return; } // create new vtk render objects (e.g. sphere for a point) SetVtkMapperImmediateModeRendering(m_VtkSelectedPolyDataMapper); SetVtkMapperImmediateModeRendering(m_VtkUnselectedPolyDataMapper); BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool needGenerateData = ls->IsGenerateDataRequired(renderer, this, GetDataNode()); if (!needGenerateData) { mitk::FloatProperty *pointSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("pointsize")); mitk::FloatProperty *contourSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("contoursize")); bool useVertexRendering = false; this->GetDataNode()->GetBoolProperty("Vertex Rendering", useVertexRendering); // only create new vtk render objects if property values were changed if (pointSizeProp && m_PointSize != pointSizeProp->GetValue()) needGenerateData = true; if (contourSizeProp && m_ContourRadius != contourSizeProp->GetValue()) needGenerateData = true; // when vertex rendering is enabled the pointset is always // drawn with opengl, thus we leave needGenerateData always false if (useVertexRendering && m_VertexRendering != useVertexRendering) { needGenerateData = false; m_VertexRendering = true; } else if (!useVertexRendering && m_VertexRendering) { m_VertexRendering = false; needGenerateData = true; } } if (needGenerateData) { this->CreateVTKRenderObjects(); ls->UpdateGenerateDataTime(); } this->ApplyAllProperties(renderer, m_ContourActor); bool showPoints = true; this->GetDataNode()->GetBoolProperty("show points", showPoints); m_UnselectedActor->SetVisibility(showPoints && !m_VertexRendering); m_SelectedActor->SetVisibility(showPoints && !m_VertexRendering); if (false && dynamic_cast(this->GetDataNode()->GetProperty("opacity")) != nullptr) { mitk::FloatProperty::Pointer pointOpacity = dynamic_cast(this->GetDataNode()->GetProperty("opacity")); float opacity = pointOpacity->GetValue(); m_ContourActor->GetProperty()->SetOpacity(opacity); m_UnselectedActor->GetProperty()->SetOpacity(opacity); m_SelectedActor->GetProperty()->SetOpacity(opacity); } bool showContour = false; this->GetDataNode()->GetBoolProperty("show contour", showContour); m_ContourActor->SetVisibility(showContour); // use vertex rendering if (m_VertexRendering) { VertexRendering(); ls->UpdateGenerateDataTime(); } } void mitk::PointSetVtkMapper3D::ResetMapper(BaseRenderer * /*renderer*/) { m_PointsAssembly->VisibilityOff(); } vtkProp *mitk::PointSetVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) { return m_PointsAssembly; } void mitk::PointSetVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) { } void mitk::PointSetVtkMapper3D::ApplyAllProperties(mitk::BaseRenderer *renderer, vtkActor *actor) { Superclass::ApplyColorAndOpacityProperties(renderer, actor); // check for color props and use it for rendering of selected/unselected points and contour // due to different params in VTK (double/float) we have to convert! // vars to convert to double unselectedColor[4] = {1.0f, 1.0f, 0.0f, 1.0f}; // yellow double selectedColor[4] = {1.0f, 0.0f, 0.0f, 1.0f}; // red double contourColor[4] = {1.0f, 0.0f, 0.0f, 1.0f}; // red // different types for color!!! mitk::Color tmpColor; double opacity = 1.0; // check if there is an unselected property if (dynamic_cast( this->GetDataNode()->GetPropertyList(renderer)->GetProperty("unselectedcolor")) != nullptr) { tmpColor = dynamic_cast( this->GetDataNode()->GetPropertyList(renderer)->GetProperty("unselectedcolor")) ->GetValue(); unselectedColor[0] = tmpColor[0]; unselectedColor[1] = tmpColor[1]; unselectedColor[2] = tmpColor[2]; unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value } else if (dynamic_cast( this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("unselectedcolor")) != nullptr) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("unselectedcolor")) ->GetValue(); unselectedColor[0] = tmpColor[0]; unselectedColor[1] = tmpColor[1]; unselectedColor[2] = tmpColor[2]; unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value } else { // check if the node has a color float unselectedColorTMP[4] = {1.0f, 1.0f, 0.0f, 1.0f}; // yellow m_DataNode->GetColor(unselectedColorTMP, nullptr); unselectedColor[0] = unselectedColorTMP[0]; unselectedColor[1] = unselectedColorTMP[1]; unselectedColor[2] = unselectedColorTMP[2]; // unselectedColor[3] stays 1.0f } // get selected property if (dynamic_cast( this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor")) != nullptr) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor")) ->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; } else if (dynamic_cast( this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("selectedcolor")) != nullptr) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("selectedcolor")) ->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; } // get contour property if (dynamic_cast( this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor")) != nullptr) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor")) ->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } else if (dynamic_cast( this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("contourcolor")) != nullptr) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("contourcolor")) ->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } if (dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("opacity")) != nullptr) { mitk::FloatProperty::Pointer pointOpacity = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("opacity")); opacity = pointOpacity->GetValue(); } else if (dynamic_cast(this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("opacity")) != nullptr) { mitk::FloatProperty::Pointer pointOpacity = dynamic_cast(this->GetDataNode()->GetPropertyList(nullptr)->GetProperty("opacity")); opacity = pointOpacity->GetValue(); } // finished color / opacity fishing! // check if a contour shall be drawn bool showContour = false; this->GetDataNode()->GetBoolProperty("show contour", showContour, renderer); if (showContour && (m_ContourActor != nullptr)) { this->CreateContour(m_WorldPositions, m_PointConnections); m_ContourActor->GetProperty()->SetColor(contourColor); m_ContourActor->GetProperty()->SetOpacity(opacity); } m_SelectedActor->GetProperty()->SetColor(selectedColor); m_SelectedActor->GetProperty()->SetOpacity(opacity); m_UnselectedActor->GetProperty()->SetColor(unselectedColor); m_UnselectedActor->GetProperty()->SetOpacity(opacity); } void mitk::PointSetVtkMapper3D::CreateContour(vtkPoints *points, vtkCellArray *m_PointConnections) { vtkSmartPointer vtkContourPolyData = vtkSmartPointer::New(); vtkSmartPointer vtkContourPolyDataMapper = vtkSmartPointer::New(); vtkSmartPointer contour = vtkSmartPointer::New(); contour->SetPoints(points); contour->SetLines(m_PointConnections); vtkSmartPointer tubeFilter = vtkSmartPointer::New(); tubeFilter->SetNumberOfSides(12); tubeFilter->SetInputData(contour); // check for property contoursize. m_ContourRadius = 0.5; mitk::FloatProperty::Pointer contourSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("contoursize")); if (contourSizeProp.IsNotNull()) m_ContourRadius = contourSizeProp->GetValue(); tubeFilter->SetRadius(m_ContourRadius); tubeFilter->Update(); // add to pipeline vtkContourPolyData->AddInputConnection(tubeFilter->GetOutputPort()); vtkContourPolyDataMapper->SetInputConnection(vtkContourPolyData->GetOutputPort()); m_ContourActor->SetMapper(vtkContourPolyDataMapper); m_PointsAssembly->AddPart(m_ContourActor); } void mitk::PointSetVtkMapper3D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) { node->AddProperty("line width", mitk::IntProperty::New(2), renderer, overwrite); node->AddProperty("pointsize", mitk::FloatProperty::New(1.0), renderer, overwrite); node->AddProperty("selectedcolor", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite); // red node->AddProperty("color", mitk::ColorProperty::New(1.0f, 1.0f, 0.0f), renderer, overwrite); // yellow node->AddProperty("opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite); node->AddProperty("show contour", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("close contour", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("contourcolor", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite); node->AddProperty("contoursize", mitk::FloatProperty::New(0.5), renderer, overwrite); node->AddProperty("show points", mitk::BoolProperty::New(true), renderer, overwrite); node->AddProperty("updateDataOnRender", mitk::BoolProperty::New(true), renderer, overwrite); node->AddProperty("Vertex Rendering", mitk::BoolProperty::New(false), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/Core/src/Rendering/mitkSurfaceVtkMapper3D.cpp b/Modules/Core/src/Rendering/mitkSurfaceVtkMapper3D.cpp index cc114feac0..70653e9154 100644 --- a/Modules/Core/src/Rendering/mitkSurfaceVtkMapper3D.cpp +++ b/Modules/Core/src/Rendering/mitkSurfaceVtkMapper3D.cpp @@ -1,532 +1,531 @@ /*=================================================================== 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 "mitkSurfaceVtkMapper3D.h" #include #include #include #include #include #include #include -#include #include #include #include #include #include #include #include #include // VTK #include #include #include #include #include #include #include #include const mitk::Surface *mitk::SurfaceVtkMapper3D::GetInput() { return static_cast(GetDataNode()->GetData()); } mitk::SurfaceVtkMapper3D::SurfaceVtkMapper3D() { m_GenerateNormals = false; } mitk::SurfaceVtkMapper3D::~SurfaceVtkMapper3D() { } void mitk::SurfaceVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if (!visible) { ls->m_Actor->VisibilityOff(); return; } // // set the input-object at time t for the mapper // mitk::Surface::Pointer input = const_cast(this->GetInput()); vtkSmartPointer polydata = input->GetVtkPolyData(this->GetTimestep()); if (polydata == nullptr) { ls->m_Actor->VisibilityOff(); return; } if (m_GenerateNormals) { ls->m_VtkPolyDataNormals->SetInputData(polydata); ls->m_VtkPolyDataMapper->SetInputConnection(ls->m_VtkPolyDataNormals->GetOutputPort()); } else { bool depthsorting = false; GetDataNode()->GetBoolProperty("Depth Sorting", depthsorting); if (depthsorting) { ls->m_DepthSort->SetInputData(polydata); ls->m_DepthSort->SetCamera(renderer->GetVtkRenderer()->GetActiveCamera()); ls->m_DepthSort->SetDirectionToBackToFront(); ls->m_DepthSort->Update(); ls->m_VtkPolyDataMapper->SetInputConnection(ls->m_DepthSort->GetOutputPort()); } else { ls->m_VtkPolyDataMapper->SetInputData(polydata); } } // // apply properties read from the PropertyList // ApplyAllProperties(renderer, ls->m_Actor); if (visible) ls->m_Actor->VisibilityOn(); } void mitk::SurfaceVtkMapper3D::ResetMapper(BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); ls->m_Actor->VisibilityOff(); } void mitk::SurfaceVtkMapper3D::ApplyMitkPropertiesToVtkProperty(mitk::DataNode *node, vtkProperty *property, mitk::BaseRenderer *renderer) { // Backface culling { mitk::BoolProperty::Pointer p; node->GetProperty(p, "Backface Culling", renderer); bool useCulling = false; if (p.IsNotNull()) useCulling = p->GetValue(); property->SetBackfaceCulling(useCulling); } // Colors { double ambient[3] = {0.5, 0.5, 0.0}; double diffuse[3] = {0.5, 0.5, 0.0}; double specular[3] = {1.0, 1.0, 1.0}; float coeff_ambient = 0.5f; float coeff_diffuse = 0.5f; float coeff_specular = 0.5f; float power_specular = 10.0f; // Color { mitk::ColorProperty::Pointer p; node->GetProperty(p, "color", renderer); if (p.IsNotNull()) { mitk::Color c = p->GetColor(); ambient[0] = c.GetRed(); ambient[1] = c.GetGreen(); ambient[2] = c.GetBlue(); diffuse[0] = c.GetRed(); diffuse[1] = c.GetGreen(); diffuse[2] = c.GetBlue(); // Setting specular color to the same, make physically no real sense, however vtk rendering slows down, if these // colors are different. specular[0] = c.GetRed(); specular[1] = c.GetGreen(); specular[2] = c.GetBlue(); } } // Ambient { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.ambientColor", renderer); if (p.IsNotNull()) { mitk::Color c = p->GetColor(); ambient[0] = c.GetRed(); ambient[1] = c.GetGreen(); ambient[2] = c.GetBlue(); } } // Diffuse { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.diffuseColor", renderer); if (p.IsNotNull()) { mitk::Color c = p->GetColor(); diffuse[0] = c.GetRed(); diffuse[1] = c.GetGreen(); diffuse[2] = c.GetBlue(); } } // Specular { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.specularColor", renderer); if (p.IsNotNull()) { mitk::Color c = p->GetColor(); specular[0] = c.GetRed(); specular[1] = c.GetGreen(); specular[2] = c.GetBlue(); } } // Ambient coeff { node->GetFloatProperty("material.ambientCoefficient", coeff_ambient, renderer); } // Diffuse coeff { node->GetFloatProperty("material.diffuseCoefficient", coeff_diffuse, renderer); } // Specular coeff { node->GetFloatProperty("material.specularCoefficient", coeff_specular, renderer); } // Specular power { node->GetFloatProperty("material.specularPower", power_specular, renderer); } property->SetAmbient(coeff_ambient); property->SetDiffuse(coeff_diffuse); property->SetSpecular(coeff_specular); property->SetSpecularPower(power_specular); property->SetAmbientColor(ambient); property->SetDiffuseColor(diffuse); property->SetSpecularColor(specular); } // Render mode { // Opacity { float opacity = 1.0f; if (node->GetOpacity(opacity, renderer)) property->SetOpacity(opacity); } // Wireframe line width { float lineWidth = 1; node->GetFloatProperty("material.wireframeLineWidth", lineWidth, renderer); property->SetLineWidth(lineWidth); } // Point size { float pointSize = 1.0f; node->GetFloatProperty("material.pointSize", pointSize, renderer); property->SetPointSize(pointSize); } // Representation { mitk::VtkRepresentationProperty::Pointer p; node->GetProperty(p, "material.representation", renderer); if (p.IsNotNull()) property->SetRepresentation(p->GetVtkRepresentation()); } // Interpolation { mitk::VtkInterpolationProperty::Pointer p; node->GetProperty(p, "material.interpolation", renderer); if (p.IsNotNull()) property->SetInterpolation(p->GetVtkInterpolation()); } } } void mitk::SurfaceVtkMapper3D::ApplyAllProperties(mitk::BaseRenderer *renderer, vtkActor * /*actor*/) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // Applying shading properties Superclass::ApplyColorAndOpacityProperties(renderer, ls->m_Actor); this->ApplyShaderProperties(renderer); // VTK Properties ApplyMitkPropertiesToVtkProperty(this->GetDataNode(), ls->m_Actor->GetProperty(), renderer); mitk::TransferFunctionProperty::Pointer transferFuncProp; this->GetDataNode()->GetProperty(transferFuncProp, "Surface.TransferFunction", renderer); if (transferFuncProp.IsNotNull()) { ls->m_VtkPolyDataMapper->SetLookupTable(transferFuncProp->GetValue()->GetColorTransferFunction()); } mitk::LookupTableProperty::Pointer lookupTableProp; this->GetDataNode()->GetProperty(lookupTableProp, "LookupTable", renderer); if (lookupTableProp.IsNotNull()) { ls->m_VtkPolyDataMapper->SetLookupTable(lookupTableProp->GetLookupTable()->GetVtkLookupTable()); } mitk::LevelWindow levelWindow; if (this->GetDataNode()->GetLevelWindow(levelWindow, renderer, "levelWindow")) { ls->m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound()); } else if (this->GetDataNode()->GetLevelWindow(levelWindow, renderer)) { ls->m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound()); } bool scalarVisibility = false; this->GetDataNode()->GetBoolProperty("scalar visibility", scalarVisibility); ls->m_VtkPolyDataMapper->SetScalarVisibility((scalarVisibility ? 1 : 0)); if (scalarVisibility) { mitk::VtkScalarModeProperty *scalarMode; if (this->GetDataNode()->GetProperty(scalarMode, "scalar mode", renderer)) ls->m_VtkPolyDataMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); else ls->m_VtkPolyDataMapper->SetScalarModeToDefault(); bool colorMode = false; this->GetDataNode()->GetBoolProperty("color mode", colorMode); ls->m_VtkPolyDataMapper->SetColorMode((colorMode ? 1 : 0)); double scalarsMin = 0; this->GetDataNode()->GetDoubleProperty("ScalarsRangeMinimum", scalarsMin, renderer); double scalarsMax = 1.0; this->GetDataNode()->GetDoubleProperty("ScalarsRangeMaximum", scalarsMax, renderer); ls->m_VtkPolyDataMapper->SetScalarRange(scalarsMin, scalarsMax); } mitk::SmartPointerProperty::Pointer imagetextureProp = dynamic_cast(GetDataNode()->GetProperty("Surface.Texture", renderer)); if (imagetextureProp.IsNotNull()) { mitk::Image *miktTexture = dynamic_cast(imagetextureProp->GetSmartPointer().GetPointer()); vtkSmartPointer vtkTxture = vtkSmartPointer::New(); // Either select the first slice of a volume if (miktTexture->GetDimension(2) > 1) { MITK_WARN << "3D Textures are not supported by VTK and MITK. The first slice of the volume will be used instead!"; mitk::ImageSliceSelector::Pointer sliceselector = mitk::ImageSliceSelector::New(); sliceselector->SetSliceNr(0); sliceselector->SetChannelNr(0); sliceselector->SetTimeNr(0); sliceselector->SetInput(miktTexture); sliceselector->Update(); vtkTxture->SetInputData(sliceselector->GetOutput()->GetVtkImageData()); } else // or just use the 2D image { vtkTxture->SetInputData(miktTexture->GetVtkImageData()); } // pass the texture to the actor ls->m_Actor->SetTexture(vtkTxture); if (ls->m_VtkPolyDataMapper->GetInput()->GetPointData()->GetTCoords() == nullptr) { MITK_ERROR << "Surface.Texture property was set, but there are no texture coordinates. Please provide texture " "coordinates for the vtkPolyData via vtkPolyData->GetPointData()->SetTCoords()."; } // if no texture is set, this will also remove a previously used texture // and reset the actor to it's default behaviour } else { ls->m_Actor->SetTexture(0); } // deprecated settings bool deprecatedUseCellData = false; this->GetDataNode()->GetBoolProperty("deprecated useCellDataForColouring", deprecatedUseCellData); bool deprecatedUsePointData = false; this->GetDataNode()->GetBoolProperty("deprecated usePointDataForColouring", deprecatedUsePointData); if (deprecatedUseCellData) { ls->m_VtkPolyDataMapper->SetColorModeToDefault(); ls->m_VtkPolyDataMapper->SetScalarRange(0, 255); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_VtkPolyDataMapper->SetScalarModeToUseCellData(); ls->m_Actor->GetProperty()->SetSpecular(1); ls->m_Actor->GetProperty()->SetSpecularPower(50); ls->m_Actor->GetProperty()->SetInterpolationToPhong(); } else if (deprecatedUsePointData) { float scalarsMin = 0; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum")) != nullptr) scalarsMin = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum"))->GetValue(); float scalarsMax = 0.1; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum")) != nullptr) scalarsMax = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum"))->GetValue(); ls->m_VtkPolyDataMapper->SetScalarRange(scalarsMin, scalarsMax); ls->m_VtkPolyDataMapper->SetColorModeToMapScalars(); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_Actor->GetProperty()->SetSpecular(1); ls->m_Actor->GetProperty()->SetSpecularPower(50); ls->m_Actor->GetProperty()->SetInterpolationToPhong(); } int deprecatedScalarMode = VTK_COLOR_MODE_DEFAULT; if (this->GetDataNode()->GetIntProperty("deprecated scalar mode", deprecatedScalarMode, renderer)) { ls->m_VtkPolyDataMapper->SetScalarMode(deprecatedScalarMode); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_Actor->GetProperty()->SetSpecular(1); ls->m_Actor->GetProperty()->SetSpecularPower(50); } // Check whether one or more ClippingProperty objects have been defined for // this node. Check both renderer specific and global property lists, since // properties in both should be considered. const PropertyList::PropertyMap *rendererProperties = this->GetDataNode()->GetPropertyList(renderer)->GetMap(); const PropertyList::PropertyMap *globalProperties = this->GetDataNode()->GetPropertyList(nullptr)->GetMap(); // Add clipping planes (if any) ls->m_ClippingPlaneCollection->RemoveAllItems(); PropertyList::PropertyMap::const_iterator it; for (it = rendererProperties->begin(); it != rendererProperties->end(); ++it) { this->CheckForClippingProperty(renderer, (*it).second.GetPointer()); } for (it = globalProperties->begin(); it != globalProperties->end(); ++it) { this->CheckForClippingProperty(renderer, (*it).second.GetPointer()); } if (ls->m_ClippingPlaneCollection->GetNumberOfItems() > 0) { ls->m_VtkPolyDataMapper->SetClippingPlanes(ls->m_ClippingPlaneCollection); } else { ls->m_VtkPolyDataMapper->RemoveAllClippingPlanes(); } } vtkProp *mitk::SurfaceVtkMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); return ls->m_Actor; } void mitk::SurfaceVtkMapper3D::CheckForClippingProperty(mitk::BaseRenderer *renderer, mitk::BaseProperty *property) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); ClippingProperty *clippingProperty = dynamic_cast(property); if ((clippingProperty != nullptr) && (clippingProperty->GetClippingEnabled())) { const Point3D &origin = clippingProperty->GetOrigin(); const Vector3D &normal = clippingProperty->GetNormal(); vtkSmartPointer clippingPlane = vtkSmartPointer::New(); clippingPlane->SetOrigin(origin[0], origin[1], origin[2]); clippingPlane->SetNormal(normal[0], normal[1], normal[2]); ls->m_ClippingPlaneCollection->AddItem(clippingPlane); } } void mitk::SurfaceVtkMapper3D::SetDefaultPropertiesForVtkProperty(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) { // Shading { node->AddProperty("material.wireframeLineWidth", mitk::FloatProperty::New(1.0f), renderer, overwrite); node->AddProperty("material.pointSize", mitk::FloatProperty::New(1.0f), renderer, overwrite); node->AddProperty("material.ambientCoefficient", mitk::FloatProperty::New(0.05f), renderer, overwrite); node->AddProperty("material.diffuseCoefficient", mitk::FloatProperty::New(0.9f), renderer, overwrite); node->AddProperty("material.specularCoefficient", mitk::FloatProperty::New(1.0f), renderer, overwrite); node->AddProperty("material.specularPower", mitk::FloatProperty::New(16.0f), renderer, overwrite); node->AddProperty("material.representation", mitk::VtkRepresentationProperty::New(), renderer, overwrite); node->AddProperty("material.interpolation", mitk::VtkInterpolationProperty::New(), renderer, overwrite); } - // Shaders - IShaderRepository *shaderRepo = CoreServices::GetShaderRepository(); - if (shaderRepo) - { - shaderRepo->AddDefaultProperties(node, renderer, overwrite); - } +// // Shaders +// IShaderRepository *shaderRepo = CoreServices::GetShaderRepository(); +// if (shaderRepo) +// { +// shaderRepo->AddDefaultProperties(node, renderer, overwrite); +// } } void mitk::SurfaceVtkMapper3D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) { node->AddProperty("color", mitk::ColorProperty::New(1.0f, 1.0f, 1.0f), renderer, overwrite); node->AddProperty("opacity", mitk::FloatProperty::New(1.0), renderer, overwrite); mitk::SurfaceVtkMapper3D::SetDefaultPropertiesForVtkProperty(node, renderer, overwrite); // Shading node->AddProperty("scalar visibility", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("color mode", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("scalar mode", mitk::VtkScalarModeProperty::New(), renderer, overwrite); mitk::Surface::Pointer surface = dynamic_cast(node->GetData()); if (surface.IsNotNull()) { if ((surface->GetVtkPolyData() != 0) && (surface->GetVtkPolyData()->GetPointData() != nullptr) && (surface->GetVtkPolyData()->GetPointData()->GetScalars() != 0)) { node->AddProperty("scalar visibility", mitk::BoolProperty::New(true), renderer, overwrite); node->AddProperty("color mode", mitk::BoolProperty::New(true), renderer, overwrite); } } // Backface culling node->AddProperty("Backface Culling", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("Depth Sorting", mitk::BoolProperty::New(false), renderer, overwrite); mitk::CoreServices::GetPropertyDescriptions()->AddDescription( "Depth Sorting", "Enables correct rendering for transparent objects by ordering polygons according to the distance " "to the camera. It is not recommended to enable this property for large surfaces (rendering might " "be slow)."); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/Core/src/Rendering/mitkVtkMapper.cpp b/Modules/Core/src/Rendering/mitkVtkMapper.cpp index 5003e99123..aad99fa7f3 100644 --- a/Modules/Core/src/Rendering/mitkVtkMapper.cpp +++ b/Modules/Core/src/Rendering/mitkVtkMapper.cpp @@ -1,161 +1,144 @@ /*=================================================================== 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 "mitkVtkMapper.h" mitk::VtkMapper::VtkMapper() { } mitk::VtkMapper::~VtkMapper() { } void mitk::VtkMapper::MitkRender(mitk::BaseRenderer *renderer, mitk::VtkPropRenderer::RenderType type) { - VtkMapperLocalStorage *ls = m_VtkMapperLSH.GetLocalStorage(renderer); - if (ls->m_ShaderProgram) - { - ls->m_ShaderProgram->Activate(); - } - switch (type) { case mitk::VtkPropRenderer::Opaque: this->MitkRenderOpaqueGeometry(renderer); break; case mitk::VtkPropRenderer::Translucent: this->MitkRenderTranslucentGeometry(renderer); break; case mitk::VtkPropRenderer::Overlay: this->MitkRenderOverlay(renderer); break; case mitk::VtkPropRenderer::Volumetric: this->MitkRenderVolumetricGeometry(renderer); break; } - - if (ls->m_ShaderProgram) - { - ls->m_ShaderProgram->Deactivate(); - } } bool mitk::VtkMapper::IsVtkBased() const { return true; } void mitk::VtkMapper::MitkRenderOverlay(BaseRenderer *renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if (!visible) return; if (this->GetVtkProp(renderer)->GetVisibility()) { GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); } } void mitk::VtkMapper::MitkRenderOpaqueGeometry(BaseRenderer *renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if (!visible) return; if (this->GetVtkProp(renderer)->GetVisibility()) { GetVtkProp(renderer)->RenderOpaqueGeometry(renderer->GetVtkRenderer()); } } void mitk::VtkMapper::MitkRenderTranslucentGeometry(BaseRenderer *renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if (!visible) return; if (this->GetVtkProp(renderer)->GetVisibility()) { GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); } } -void mitk::VtkMapper::ApplyShaderProperties(mitk::BaseRenderer *renderer) +void mitk::VtkMapper::ApplyShaderProperties(mitk::BaseRenderer *) { - IShaderRepository *shaderRepo = CoreServices::GetShaderRepository(); - if (shaderRepo) - { - VtkMapperLocalStorage *ls = m_VtkMapperLSH.GetLocalStorage(renderer); - shaderRepo->UpdateShaderProgram(ls->m_ShaderProgram, this->GetDataNode(), renderer); - } } void mitk::VtkMapper::MitkRenderVolumetricGeometry(BaseRenderer *renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if (!visible) return; if (GetVtkProp(renderer)->GetVisibility()) { GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); } } bool mitk::VtkMapper::HasVtkProp(const vtkProp *prop, BaseRenderer *renderer) { vtkProp *myProp = this->GetVtkProp(renderer); // TODO: check if myProp is a vtkAssembly and if so, check if prop is contained in its leafs return (prop == myProp); } void mitk::VtkMapper::SetVtkMapperImmediateModeRendering(vtkMapper *mapper) { if (mapper) mapper->SetImmediateModeRendering(mitk::VtkPropRenderer::useImmediateModeRendering()); } void mitk::VtkMapper::UpdateVtkTransform(mitk::BaseRenderer *renderer) { vtkLinearTransform *vtktransform = GetDataNode()->GetVtkTransform(this->GetTimestep()); vtkProp3D *prop = dynamic_cast(GetVtkProp(renderer)); if (prop) prop->SetUserTransform(vtktransform); } void mitk::VtkMapper::ApplyColorAndOpacityProperties(BaseRenderer *renderer, vtkActor *actor) { float rgba[4] = {1.0f, 1.0f, 1.0f, 1.0f}; DataNode *node = GetDataNode(); // check for color prop and use it for rendering if it exists node->GetColor(rgba, renderer, "color"); // check for opacity prop and use it for rendering if it exists node->GetOpacity(rgba[3], renderer, "opacity"); double drgba[4] = {rgba[0], rgba[1], rgba[2], rgba[3]}; actor->GetProperty()->SetColor(drgba); actor->GetProperty()->SetOpacity(drgba[3]); } diff --git a/Modules/Core/src/Rendering/vtkMitkLevelWindowFilter.cpp b/Modules/Core/src/Rendering/vtkMitkLevelWindowFilter.cpp index e95629279c..1fca3768d1 100644 --- a/Modules/Core/src/Rendering/vtkMitkLevelWindowFilter.cpp +++ b/Modules/Core/src/Rendering/vtkMitkLevelWindowFilter.cpp @@ -1,589 +1,589 @@ /*=================================================================== 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 "vtkMitkLevelWindowFilter.h" #include "vtkObjectFactory.h" #include #include #include #include #include #include #include #include // used for acos etc. #include // used for PI #include #include static const double PI = itk::Math::pi; vtkStandardNewMacro(vtkMitkLevelWindowFilter); vtkMitkLevelWindowFilter::vtkMitkLevelWindowFilter() : m_LookupTable(nullptr), m_OpacityFunction(nullptr), m_MinOpacity(0.0), m_MaxOpacity(255.0) { // MITK_INFO << "mitk level/window filter uses " << GetNumberOfThreads() << " thread(s)"; } vtkMitkLevelWindowFilter::~vtkMitkLevelWindowFilter() { } -unsigned long int vtkMitkLevelWindowFilter::GetMTime() +vtkMTimeType vtkMitkLevelWindowFilter::GetMTime() { - unsigned long mTime = this->vtkObject::GetMTime(); - unsigned long time; + vtkMTimeType mTime = this->vtkObject::GetMTime(); + vtkMTimeType time; if (this->m_LookupTable != nullptr) { time = this->m_LookupTable->GetMTime(); mTime = (time > mTime ? time : mTime); } return mTime; } void vtkMitkLevelWindowFilter::SetLookupTable(vtkScalarsToColors *lookupTable) { if (m_LookupTable != lookupTable) { m_LookupTable = lookupTable; this->Modified(); } } vtkScalarsToColors *vtkMitkLevelWindowFilter::GetLookupTable() { return m_LookupTable; } void vtkMitkLevelWindowFilter::SetOpacityPiecewiseFunction(vtkPiecewiseFunction *opacityFunction) { if (m_OpacityFunction != opacityFunction) { m_OpacityFunction = opacityFunction; this->Modified(); } } // This code was copied from the iil. The template works only for float and double. // Internal method which should never be used anywhere else and should not be in th header. // Convert color pixels from (R,G,B) to (H,S,I). // Reference: "Digital Image Processing, 2nd. edition", R. Gonzalez and R. Woods. Prentice Hall, 2002. template void RGBtoHSI(T *RGB, T *HSI) { T R = RGB[0], G = RGB[1], B = RGB[2], nR = (R < 0 ? 0 : (R > 255 ? 255 : R)) / 255, nG = (G < 0 ? 0 : (G > 255 ? 255 : G)) / 255, nB = (B < 0 ? 0 : (B > 255 ? 255 : B)) / 255, m = nR < nG ? (nR < nB ? nR : nB) : (nG < nB ? nG : nB), theta = (T)(std::acos(0.5f * ((nR - nG) + (nR - nB)) / std::sqrt(std::pow(nR - nG, 2) + (nR - nB) * (nG - nB))) * 180 / PI), sum = nR + nG + nB; T H = 0, S = 0, I = 0; if (theta > 0) H = (nB <= nG) ? theta : 360 - theta; if (sum > 0) S = 1 - 3 / sum * m; I = sum / 3; HSI[0] = (T)H; HSI[1] = (T)S; HSI[2] = (T)I; } // This code was copied from the iil. The template works only for float and double. // Internal method which should never be used anywhere else and should not be in th header. // Convert color pixels from (H,S,I) to (R,G,B). template void HSItoRGB(T *HSI, T *RGB) { T H = (T)HSI[0], S = (T)HSI[1], I = (T)HSI[2], a = I * (1 - S), R = 0, G = 0, B = 0; if (H < 120) { B = a; R = (T)(I * (1 + S * std::cos(H * PI / 180) / std::cos((60 - H) * PI / 180))); G = 3 * I - (R + B); } else if (H < 240) { H -= 120; R = a; G = (T)(I * (1 + S * std::cos(H * PI / 180) / std::cos((60 - H) * PI / 180))); B = 3 * I - (R + G); } else { H -= 240; G = a; B = (T)(I * (1 + S * std::cos(H * PI / 180) / std::cos((60 - H) * PI / 180))); R = 3 * I - (G + B); } R *= 255; G *= 255; B *= 255; RGB[0] = (T)(R < 0 ? 0 : (R > 255 ? 255 : R)); RGB[1] = (T)(G < 0 ? 0 : (G > 255 ? 255 : G)); RGB[2] = (T)(B < 0 ? 0 : (B > 255 ? 255 : B)); } // Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnRGBA(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], double *clippingBounds, T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkLookupTable *lookupTable; const int maxC = inData->GetNumberOfScalarComponents(); double tableRange[2]; lookupTable = dynamic_cast(self->GetLookupTable()); lookupTable->GetTableRange(tableRange); // parameters for RGB level window const double scale = (tableRange[1] - tableRange[0] > 0 ? 255.0 / (tableRange[1] - tableRange[0]) : 0.0); const double bias = tableRange[0] * scale; // parameters for opaque level window const double scaleOpac = (self->GetMaxOpacity() - self->GetMinOpacity() > 0 ? 255.0 / (self->GetMaxOpacity() - self->GetMinOpacity()) : 0.0); const double biasOpac = self->GetMinOpacity() * scaleOpac; int y = outExt[2]; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { T *inputSI = inputIt.BeginSpan(); T *outputSI = outputIt.BeginSpan(); T *outputSIEnd = outputIt.EndSpan(); if (y >= clippingBounds[2] && y < clippingBounds[3]) { int x = outExt[0]; while (outputSI != outputSIEnd) { if (x >= clippingBounds[0] && x < clippingBounds[1]) { double rgb[3], alpha, hsi[3]; // level/window mechanism for intensity in HSI space rgb[0] = static_cast(*inputSI); inputSI++; rgb[1] = static_cast(*inputSI); inputSI++; rgb[2] = static_cast(*inputSI); inputSI++; RGBtoHSI(rgb, hsi); hsi[2] = hsi[2] * 255.0 * scale - bias; hsi[2] = (hsi[2] > 255.0 ? 255 : (hsi[2] < 0.0 ? 0 : hsi[2])); hsi[2] /= 255.0; HSItoRGB(hsi, rgb); *outputSI = static_cast(rgb[0]); outputSI++; *outputSI = static_cast(rgb[1]); outputSI++; *outputSI = static_cast(rgb[2]); outputSI++; unsigned char finalAlpha = 255; // RGBA case if (maxC >= 4) { // level/window mechanism for opacity alpha = static_cast(*inputSI); inputSI++; alpha = alpha * scaleOpac - biasOpac; if (alpha > 255.0) { alpha = 255.0; } else if (alpha < 0.0) { alpha = 0.0; } finalAlpha = static_cast(alpha); for (int c = 4; c < maxC; c++) inputSI++; } *outputSI = static_cast(finalAlpha); outputSI++; } else { inputSI += maxC; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; } x++; } } else { while (outputSI != outputSIEnd) { *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; } } inputIt.NextSpan(); outputIt.NextSpan(); y++; } } // Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnScalarsFast( vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); double tableRange[2]; // access vtkLookupTable vtkLookupTable *lookupTable = dynamic_cast(self->GetLookupTable()); lookupTable->GetTableRange(tableRange); // access elements of the vtkLookupTable const int *realLookupTable = reinterpret_cast(lookupTable->GetTable()->GetPointer(0)); int maxIndex = lookupTable->GetNumberOfColors() - 1; const float scale = (tableRange[1] - tableRange[0] > 0 ? (maxIndex + 1) / (tableRange[1] - tableRange[0]) : 0.0); // ensuring that starting point is zero float bias = -tableRange[0] * scale; // due to later conversion to int for rounding bias += 0.5f; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { unsigned char *outputSI = outputIt.BeginSpan(); unsigned char *outputSIEnd = outputIt.EndSpan(); T *inputSI = inputIt.BeginSpan(); while (outputSI != outputSIEnd) { // map to an index int idx = static_cast(*inputSI * scale + bias); if (idx < 0) idx = 0; else if (idx > maxIndex) idx = maxIndex; *reinterpret_cast(outputSI) = realLookupTable[idx]; inputSI++; outputSI += 4; } inputIt.NextSpan(); outputIt.NextSpan(); } } // Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnScalars(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], double *clippingBounds, T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkScalarsToColors *lookupTable = self->GetLookupTable(); int y = outExt[2]; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { unsigned char *outputSI = outputIt.BeginSpan(); unsigned char *outputSIEnd = outputIt.EndSpan(); // do we iterate over the inner vertical clipping bounds if (y >= clippingBounds[2] && y < clippingBounds[3]) { T *inputSI = inputIt.BeginSpan(); int x = outExt[0]; while (outputSI != outputSIEnd) { // is this pixel within horizontal clipping bounds if (x >= clippingBounds[0] && x < clippingBounds[1]) { // fetching original value double grayValue = static_cast(*inputSI); // applying lookuptable - copy the 4 (RGBA) chars as a single int *reinterpret_cast(outputSI) = *reinterpret_cast(lookupTable->MapValue(grayValue)); } else { // outer horizontal clipping bounds - write a transparent RGBA pixel as a single int *reinterpret_cast(outputSI) = 0; } inputSI++; outputSI += 4; x++; } } else { // outer vertical clipping bounds - write a transparent RGBA line as ints while (outputSI != outputSIEnd) { *reinterpret_cast(outputSI) = 0; outputSI += 4; } } inputIt.NextSpan(); outputIt.NextSpan(); y++; } } // Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnScalarsCTF(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], double *clippingBounds, T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkColorTransferFunction *lookupTable = dynamic_cast(self->GetLookupTable()); vtkPiecewiseFunction *opacityFunction = self->GetOpacityPiecewiseFunction(); int y = outExt[2]; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { unsigned char *outputSI = outputIt.BeginSpan(); unsigned char *outputSIEnd = outputIt.EndSpan(); // do we iterate over the inner vertical clipping bounds if (y >= clippingBounds[2] && y < clippingBounds[3]) { T *inputSI = inputIt.BeginSpan(); int x = outExt[0]; while (outputSI != outputSIEnd) { // is this pixel within horizontal clipping bounds if (x >= clippingBounds[0] && x < clippingBounds[1]) { // fetching original value double grayValue = static_cast(*inputSI); // applying directly colortransferfunction // because vtkColorTransferFunction::MapValue is not threadsafe double rgba[4]; lookupTable->GetColor(grayValue, rgba); // RGB mapping rgba[3] = 1.0; if (opacityFunction) rgba[3] = opacityFunction->GetValue(grayValue); // Alpha mapping for (int i = 0; i < 4; ++i) { outputSI[i] = static_cast(255.0 * rgba[i] + 0.5); } } else { // outer horizontal clipping bounds - write a transparent RGBA pixel as a single int *reinterpret_cast(outputSI) = 0; } inputSI++; outputSI += 4; x++; } } else { // outer vertical clipping bounds - write a transparent RGBA line as ints while (outputSI != outputSIEnd) { *reinterpret_cast(outputSI) = 0; outputSI += 4; } } inputIt.NextSpan(); outputIt.NextSpan(); y++; } } int vtkMitkLevelWindowFilter::RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) { vtkInformation *outInfo = outputVector->GetInformationObject(0); // do nothing except copy scalar type info this->CopyInputArrayAttributesToOutput(request, inputVector, outputVector); vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 4); return 1; } // Method to run the filter in different threads. void vtkMitkLevelWindowFilter::ThreadedExecute(vtkImageData *inData, vtkImageData *outData, int extent[6], int /*id*/) { if (inData->GetNumberOfScalarComponents() > 2) { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnRGBA(this, inData, outData, extent, m_ClippingBounds, static_cast(nullptr))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else { bool dontClip = extent[2] >= m_ClippingBounds[2] && extent[3] <= m_ClippingBounds[3] && extent[0] >= m_ClippingBounds[0] && extent[1] <= m_ClippingBounds[1]; if (this->GetLookupTable()) this->GetLookupTable()->Build(); vtkLookupTable *vlt = dynamic_cast(this->GetLookupTable()); vtkColorTransferFunction *ctf = dynamic_cast(this->GetLookupTable()); bool linearLookupTable = vlt && vlt->GetScale() == VTK_SCALE_LINEAR; bool useFast = dontClip && linearLookupTable; if (ctf) { switch (inData->GetScalarType()) { vtkTemplateMacro(vtkApplyLookupTableOnScalarsCTF( this, inData, outData, extent, m_ClippingBounds, static_cast(nullptr))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else if (useFast) { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnScalarsFast(this, inData, outData, extent, static_cast(nullptr))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else { switch (inData->GetScalarType()) { vtkTemplateMacro(vtkApplyLookupTableOnScalars( this, inData, outData, extent, m_ClippingBounds, static_cast(nullptr))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } } } // void vtkMitkLevelWindowFilter::ExecuteInformation( // vtkImageData *vtkNotUsed(inData), vtkImageData *vtkNotUsed(outData)) //{ //} void vtkMitkLevelWindowFilter::SetMinOpacity(double minOpacity) { m_MinOpacity = minOpacity; } inline double vtkMitkLevelWindowFilter::GetMinOpacity() const { return m_MinOpacity; } void vtkMitkLevelWindowFilter::SetMaxOpacity(double maxOpacity) { m_MaxOpacity = maxOpacity; } inline double vtkMitkLevelWindowFilter::GetMaxOpacity() const { return m_MaxOpacity; } void vtkMitkLevelWindowFilter::SetClippingBounds(double *bounds) // TODO does double[4] work?? { for (unsigned int i = 0; i < 4; ++i) m_ClippingBounds[i] = bounds[i]; } diff --git a/Modules/Core/src/mitkCoreActivator.cpp b/Modules/Core/src/mitkCoreActivator.cpp index ac2a072d41..785e45b8e9 100644 --- a/Modules/Core/src/mitkCoreActivator.cpp +++ b/Modules/Core/src/mitkCoreActivator.cpp @@ -1,457 +1,324 @@ /*=================================================================== 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 "mitkCoreActivator.h" // File IO #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkDicomSeriesReaderService.h" #include "mitkLegacyFileWriterService.h" #include #include #include // Micro Services #include #include #include #include #include #include #include #include #include #include // ITK "injects" static initialization code for IO factories // via the itkImageIOFactoryRegisterManager.h header (which // is generated in the application library build directory). // To ensure that the code is called *before* the CppMicroServices // static initialization code (which triggers the Activator::Start // method), we include the ITK header here. #include void HandleMicroServicesMessages(us::MsgType type, const char *msg) { switch (type) { case us::DebugMsg: MITK_DEBUG << msg; break; case us::InfoMsg: MITK_INFO << msg; break; case us::WarningMsg: MITK_WARN << msg; break; case us::ErrorMsg: MITK_ERROR << msg; break; } } void AddMitkAutoLoadPaths(const std::string &programPath) { us::ModuleSettings::AddAutoLoadPath(programPath); #ifdef __APPLE__ // Walk up three directories since that is where the .dylib files are located // for build trees. std::string additionalPath = programPath; bool addPath = true; for (int i = 0; i < 3; ++i) { std::size_t index = additionalPath.find_last_of('/'); if (index != std::string::npos) { additionalPath = additionalPath.substr(0, index); } else { addPath = false; break; } } if (addPath) { us::ModuleSettings::AddAutoLoadPath(additionalPath); } #endif } -class ShaderRepositoryTracker : public us::ServiceTracker -{ -public: - ShaderRepositoryTracker() : Superclass(us::GetModuleContext()) {} - virtual void Close() override - { - us::GetModuleContext()->RemoveModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent); - Superclass::Close(); - } - - virtual void Open() override - { - us::GetModuleContext()->AddModuleListener(this, &ShaderRepositoryTracker::HandleModuleEvent); - Superclass::Open(); - } - -private: - typedef us::ServiceTracker Superclass; - - TrackedType AddingService(const ServiceReferenceType &reference) override - { - mitk::IShaderRepository *shaderRepo = Superclass::AddingService(reference); - if (shaderRepo) - { - // Add all existing shaders from modules to the new shader repository. - // If the shader repository is registered in a modules activator, the - // GetLoadedModules() function call below will also return the module - // which is currently registering the repository. The HandleModuleEvent - // method contains code to avoid double registrations due to a fired - // ModuleEvent::LOADED event after the activators Load() method finished. - std::vector modules = us::ModuleRegistry::GetLoadedModules(); - for (std::vector::const_iterator iter = modules.begin(), endIter = modules.end(); iter != endIter; - ++iter) - { - this->AddModuleShaderToRepository(*iter, shaderRepo); - } - - m_ShaderRepositories.push_back(shaderRepo); - } - return shaderRepo; - } - - void RemovedService(const ServiceReferenceType & /*reference*/, TrackedType tracked) override - { - m_ShaderRepositories.erase(std::remove(m_ShaderRepositories.begin(), m_ShaderRepositories.end(), tracked), - m_ShaderRepositories.end()); - } - - void HandleModuleEvent(const us::ModuleEvent moduleEvent) - { - if (moduleEvent.GetType() == us::ModuleEvent::LOADED) - { - std::vector shaderRepos; - for (std::map>>::const_iterator - shaderMapIter = m_ModuleIdToShaderIds.begin(), - shaderMapEndIter = m_ModuleIdToShaderIds.end(); - shaderMapIter != shaderMapEndIter; - ++shaderMapIter) - { - if (shaderMapIter->second.find(moduleEvent.GetModule()->GetModuleId()) == shaderMapIter->second.end()) - { - shaderRepos.push_back(shaderMapIter->first); - } - } - AddModuleShadersToRepositories(moduleEvent.GetModule(), shaderRepos); - } - else if (moduleEvent.GetType() == us::ModuleEvent::UNLOADED) - { - RemoveModuleShadersFromRepositories(moduleEvent.GetModule(), m_ShaderRepositories); - } - } - - void AddModuleShadersToRepositories(us::Module *module, const std::vector &shaderRepos) - { - // search and load shader files - std::vector shaderResources = module->FindResources("Shaders", "*.xml", true); - for (std::vector::iterator i = shaderResources.begin(); i != shaderResources.end(); ++i) - { - if (*i) - { - us::ModuleResourceStream rs(*i); - for (const auto &shaderRepo : shaderRepos) - { - int id = (shaderRepo)->LoadShader(rs, i->GetBaseName()); - if (id >= 0) - { - m_ModuleIdToShaderIds[shaderRepo][module->GetModuleId()].push_back(id); - } - } - rs.seekg(0, std::ios_base::beg); - } - } - } - - void AddModuleShaderToRepository(us::Module *module, mitk::IShaderRepository *shaderRepo) - { - std::vector shaderRepos; - shaderRepos.push_back(shaderRepo); - this->AddModuleShadersToRepositories(module, shaderRepos); - } - - void RemoveModuleShadersFromRepositories(us::Module *module, - const std::vector &shaderRepos) - { - for (const auto &shaderRepo : shaderRepos) - { - std::map> &moduleIdToShaderIds = m_ModuleIdToShaderIds[shaderRepo]; - std::map>::iterator shaderIdsIter = moduleIdToShaderIds.find(module->GetModuleId()); - if (shaderIdsIter != moduleIdToShaderIds.end()) - { - for (std::vector::iterator idIter = shaderIdsIter->second.begin(); idIter != shaderIdsIter->second.end(); - ++idIter) - { - (shaderRepo)->UnloadShader(*idIter); - } - moduleIdToShaderIds.erase(shaderIdsIter); - } - } - } - -private: - // Maps to each shader repository a map containing module ids and related - // shader registration ids - std::map>> m_ModuleIdToShaderIds; - std::vector m_ShaderRepositories; -}; - class FixedNiftiImageIO : public itk::NiftiImageIO { public: /** Standard class typedefs. */ typedef FixedNiftiImageIO Self; typedef itk::NiftiImageIO Superclass; typedef itk::SmartPointer Pointer; /** Method for creation through the object factory. */ itkNewMacro(Self) /** Run-time type information (and related methods). */ itkTypeMacro(FixedNiftiImageIO, Superclass) virtual bool SupportsDimension(unsigned long dim) override { return dim > 1 && dim < 5; } }; void MitkCoreActivator::Load(us::ModuleContext *context) { // Handle messages from CppMicroServices us::installMsgHandler(HandleMicroServicesMessages); this->m_Context = context; // Add the current application directory to the auto-load paths. // This is useful for third-party executables. std::string programPath = mitk::IOUtil::GetProgramPath(); if (programPath.empty()) { MITK_WARN << "Could not get the program path."; } else { AddMitkAutoLoadPaths(programPath); } - m_ShaderRepositoryTracker.reset(new ShaderRepositoryTracker); - // m_RenderingManager = mitk::RenderingManager::New(); // context->RegisterService(renderingManager.GetPointer()); m_PlanePositionManager.reset(new mitk::PlanePositionManagerService); context->RegisterService(m_PlanePositionManager.get()); m_PropertyAliases.reset(new mitk::PropertyAliases); context->RegisterService(m_PropertyAliases.get()); m_PropertyDescriptions.reset(new mitk::PropertyDescriptions); context->RegisterService(m_PropertyDescriptions.get()); m_PropertyExtensions.reset(new mitk::PropertyExtensions); context->RegisterService(m_PropertyExtensions.get()); m_PropertyFilters.reset(new mitk::PropertyFilters); context->RegisterService(m_PropertyFilters.get()); m_PropertyPersistence.reset(new mitk::PropertyPersistence); context->RegisterService(m_PropertyPersistence.get()); m_MimeTypeProvider.reset(new mitk::MimeTypeProvider); m_MimeTypeProvider->Start(); m_MimeTypeProviderReg = context->RegisterService(m_MimeTypeProvider.get()); this->RegisterDefaultMimeTypes(); this->RegisterItkReaderWriter(); this->RegisterVtkReaderWriter(); // Add custom Reader / Writer Services m_FileReaders.push_back(new mitk::PointSetReaderService()); m_FileWriters.push_back(new mitk::PointSetWriterService()); m_FileReaders.push_back(new mitk::GeometryDataReaderService()); m_FileWriters.push_back(new mitk::GeometryDataWriterService()); m_FileReaders.push_back(new mitk::DicomSeriesReaderService()); m_FileReaders.push_back(new mitk::RawImageFileReaderService()); - m_ShaderRepositoryTracker->Open(); - /* There IS an option to exchange ALL vtkTexture instances against vtkNeverTranslucentTextureFactory. This code is left here as a reminder, just in case we might need to do that some time. vtkNeverTranslucentTextureFactory* textureFactory = vtkNeverTranslucentTextureFactory::New(); vtkObjectFactory::RegisterFactory( textureFactory ); textureFactory->Delete(); */ this->RegisterLegacyWriter(); } void MitkCoreActivator::Unload(us::ModuleContext *) { for (auto &elem : m_FileReaders) { delete elem; } for (auto &elem : m_FileWriters) { delete elem; } for (auto &elem : m_FileIOs) { delete elem; } for (auto &elem : m_LegacyWriters) { delete elem; } // The mitk::ModuleContext* argument of the Unload() method // will always be 0 for the Mitk library. It makes no sense // to use it at this stage anyway, since all libraries which // know about the module system have already been unloaded. // we need to close the internal service tracker of the // MimeTypeProvider class here. Otherwise it // would hold on to the ModuleContext longer than it is // actually valid. m_MimeTypeProviderReg.Unregister(); m_MimeTypeProvider->Stop(); for (std::vector::const_iterator mimeTypeIter = m_DefaultMimeTypes.begin(), iterEnd = m_DefaultMimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) { delete *mimeTypeIter; } - - m_ShaderRepositoryTracker->Close(); } void MitkCoreActivator::RegisterDefaultMimeTypes() { // Register some default mime-types std::vector mimeTypes = mitk::IOMimeTypes::Get(); for (std::vector::const_iterator mimeTypeIter = mimeTypes.begin(), iterEnd = mimeTypes.end(); mimeTypeIter != iterEnd; ++mimeTypeIter) { m_DefaultMimeTypes.push_back(*mimeTypeIter); m_Context->RegisterService(m_DefaultMimeTypes.back()); } } void MitkCoreActivator::RegisterItkReaderWriter() { std::list allobjects = itk::ObjectFactoryBase::CreateAllInstance("itkImageIOBase"); for (auto &allobject : allobjects) { itk::ImageIOBase *io = dynamic_cast(allobject.GetPointer()); // NiftiImageIO does not provide a correct "SupportsDimension()" methods // and the supported read/write extensions are not ordered correctly if (dynamic_cast(io)) continue; // Use a custom mime-type for GDCMImageIO below if (dynamic_cast(allobject.GetPointer())) { // MITK provides its own DICOM reader (which internally uses GDCMImageIO). continue; } if (io) { m_FileIOs.push_back(new mitk::ItkImageIO(io)); } else { MITK_WARN << "Error ImageIO factory did not return an ImageIOBase: " << (allobject)->GetNameOfClass(); } } FixedNiftiImageIO::Pointer itkNiftiIO = FixedNiftiImageIO::New(); mitk::ItkImageIO *niftiIO = new mitk::ItkImageIO(mitk::IOMimeTypes::NIFTI_MIMETYPE(), itkNiftiIO.GetPointer(), 0); m_FileIOs.push_back(niftiIO); } void MitkCoreActivator::RegisterVtkReaderWriter() { m_FileIOs.push_back(new mitk::SurfaceVtkXmlIO()); m_FileIOs.push_back(new mitk::SurfaceStlIO()); m_FileIOs.push_back(new mitk::SurfaceVtkLegacyIO()); m_FileIOs.push_back(new mitk::ImageVtkXmlIO()); m_FileIOs.push_back(new mitk::ImageVtkLegacyIO()); } void MitkCoreActivator::RegisterLegacyWriter() { std::list allobjects = itk::ObjectFactoryBase::CreateAllInstance("IOWriter"); for (std::list::iterator i = allobjects.begin(); i != allobjects.end(); ++i) { mitk::FileWriter::Pointer io = dynamic_cast(i->GetPointer()); if (io) { std::string description = std::string("Legacy ") + io->GetNameOfClass() + " Writer"; mitk::IFileWriter *writer = new mitk::LegacyFileWriterService(io, description); m_LegacyWriters.push_back(writer); } else { MITK_ERROR << "Error IOWriter override is not of type mitk::FileWriter: " << (*i)->GetNameOfClass() << std::endl; } } } US_EXPORT_MODULE_ACTIVATOR(MitkCoreActivator) // Call CppMicroservices initialization code at the end of the file. // This especially ensures that VTK object factories have already // been registered (VTK initialization code is injected by implicitly // include VTK header files at the top of this file). US_INITIALIZE_MODULE diff --git a/Modules/Core/src/mitkCoreActivator.h b/Modules/Core/src/mitkCoreActivator.h index a6c274a997..7cdbce2b57 100644 --- a/Modules/Core/src/mitkCoreActivator.h +++ b/Modules/Core/src/mitkCoreActivator.h @@ -1,86 +1,82 @@ /*=================================================================== 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 MITKCOREACTIVATOR_H_ #define MITKCOREACTIVATOR_H_ // File IO #include #include #include -#include - #include #include #include #include #include #include #include // Micro Services #include #include #include #include #include /* * This is the module activator for the "Mitk" module. It registers core services * like ... */ class MitkCoreActivator : public us::ModuleActivator { public: void Load(us::ModuleContext *context) override; void Unload(us::ModuleContext *) override; private: void HandleModuleEvent(const us::ModuleEvent moduleEvent); void RegisterDefaultMimeTypes(); void RegisterItkReaderWriter(); void RegisterVtkReaderWriter(); void RegisterLegacyWriter(); - std::unique_ptr> m_ShaderRepositoryTracker; - // mitk::RenderingManager::Pointer m_RenderingManager; std::unique_ptr m_PlanePositionManager; std::unique_ptr m_PropertyAliases; std::unique_ptr m_PropertyDescriptions; std::unique_ptr m_PropertyExtensions; std::unique_ptr m_PropertyFilters; std::unique_ptr m_PropertyPersistence; std::unique_ptr m_MimeTypeProvider; // File IO std::vector m_FileReaders; std::vector m_FileWriters; std::vector m_FileIOs; std::vector m_LegacyWriters; std::vector m_DefaultMimeTypes; us::ServiceRegistration m_MimeTypeProviderReg; us::ModuleContext *m_Context; }; #endif // MITKCOREACTIVATOR_H_ diff --git a/Modules/Core/src/mitkCoreServices.cpp b/Modules/Core/src/mitkCoreServices.cpp index 827a650b88..030ce40ecd 100644 --- a/Modules/Core/src/mitkCoreServices.cpp +++ b/Modules/Core/src/mitkCoreServices.cpp @@ -1,134 +1,126 @@ /*=================================================================== 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 "mitkCoreServices.h" #include #include #include #include #include #include -#include #include #include #include #include #include #include namespace mitk { itk::SimpleFastMutexLock &s_ContextToServicesMapMutex() { static itk::SimpleFastMutexLock mutex; return mutex; } std::map> &s_ContextToServicesMap() { static std::map> serviceMap; return serviceMap; } template static S *GetCoreService(us::ModuleContext *context) { if (context == nullptr) context = us::GetModuleContext(); S *coreService = nullptr; us::ServiceReference serviceRef = context->GetServiceReference(); if (serviceRef) { coreService = context->GetService(serviceRef); } assert(coreService && "Asserting non-nullptr MITK core service"); { itk::MutexLockHolder l(s_ContextToServicesMapMutex()); s_ContextToServicesMap()[context].insert(std::make_pair(coreService, serviceRef)); } return coreService; } - IShaderRepository *CoreServices::GetShaderRepository() - { - static us::ServiceTracker tracker(us::GetModuleContext()); - tracker.Open(); - return tracker.GetService(); - } - IPropertyAliases *CoreServices::GetPropertyAliases(us::ModuleContext *context) { return GetCoreService(context); } IPropertyDescriptions *CoreServices::GetPropertyDescriptions(us::ModuleContext *context) { return GetCoreService(context); } IPropertyExtensions *CoreServices::GetPropertyExtensions(us::ModuleContext *context) { return GetCoreService(context); } IPropertyFilters *CoreServices::GetPropertyFilters(us::ModuleContext *context) { return GetCoreService(context); } IPropertyPersistence *CoreServices::GetPropertyPersistence(us::ModuleContext *context) { return GetCoreService(context); } IMimeTypeProvider *CoreServices::GetMimeTypeProvider(us::ModuleContext *context) { return GetCoreService(context); } bool CoreServices::Unget(us::ModuleContext *context, const std::string & /*interfaceId*/, void *service) { bool success = false; itk::MutexLockHolder l(s_ContextToServicesMapMutex()); std::map>::iterator iter = s_ContextToServicesMap().find(context); if (iter != s_ContextToServicesMap().end()) { std::map::iterator iter2 = iter->second.find(service); if (iter2 != iter->second.end()) { us::ServiceReferenceU serviceRef = iter2->second; if (serviceRef) { success = context->UngetService(serviceRef); if (success) { iter->second.erase(iter2); } } } } return success; } } diff --git a/Modules/Core/test/files.cmake b/Modules/Core/test/files.cmake index a79faa1555..ccf17821cc 100644 --- a/Modules/Core/test/files.cmake +++ b/Modules/Core/test/files.cmake @@ -1,200 +1,199 @@ # tests with no extra command line parameter set(MODULE_TESTS # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code. # # Example: #mitkMyTest #this test is commented out because of bug 12345 # # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and # mark it as critical. ################## DISABLED TESTS ################################################# #mitkAbstractTransformGeometryTest.cpp #seems as tested class mitkExternAbstractTransformGeometry doesnt exist any more #mitkStateMachineContainerTest.cpp #rewrite test, indirect since no longer exported Bug 14529 #mitkRegistrationBaseTest.cpp #tested class mitkRegistrationBase doesn't exist any more #mitkSegmentationInterpolationTest.cpp #file doesn't exist! #mitkPipelineSmartPointerCorrectnessTest.cpp #file doesn't exist! #mitkITKThreadingTest.cpp #test outdated because itk::Semaphore was removed from ITK #mitkAbstractTransformPlaneGeometryTest.cpp #mitkVtkAbstractTransformPlaneGeometry doesn't exist any more #mitkTestUtilSharedLibrary.cpp #Linker problem with this test... #mitkTextOverlay2DSymbolsRenderingTest.cpp #Implementation of the tested feature is not finished yet. Ask Christoph or see bug 15104 for details. ################# RUNNING TESTS ################################################### mitkAccessByItkTest.cpp mitkCoreObjectFactoryTest.cpp mitkDataNodeTest.cpp mitkMaterialTest.cpp mitkActionTest.cpp mitkDispatcherTest.cpp mitkEnumerationPropertyTest.cpp mitkFileReaderRegistryTest.cpp #mitkFileWriterRegistryTest.cpp mitkFloatToStringTest.cpp mitkGenericPropertyTest.cpp mitkGeometry3DTest.cpp mitkGeometry3DEqualTest.cpp mitkGeometryDataIOTest.cpp mitkGeometryDataToSurfaceFilterTest.cpp mitkImageCastTest.cpp mitkImageEqualTest.cpp mitkImageDataItemTest.cpp mitkImageGeneratorTest.cpp mitkIOUtilTest.cpp mitkBaseDataTest.cpp mitkImportItkImageTest.cpp mitkGrabItkImageMemoryTest.cpp mitkInstantiateAccessFunctionTest.cpp mitkLevelWindowTest.cpp mitkMessageTest.cpp mitkPixelTypeTest.cpp mitkPlaneGeometryTest.cpp mitkPointSetTest.cpp mitkPointSetEqualTest.cpp mitkPointSetFileIOTest.cpp mitkPointSetOnEmptyTest.cpp mitkPointSetLocaleTest.cpp mitkPointSetWriterTest.cpp mitkPointSetReaderTest.cpp mitkPointSetPointOperationsTest.cpp mitkProgressBarTest.cpp mitkPropertyTest.cpp mitkPropertyListTest.cpp mitkPropertyPersistenceTest.cpp mitkPropertyPersistenceInfoTest.cpp mitkSlicedGeometry3DTest.cpp mitkSliceNavigationControllerTest.cpp mitkSurfaceTest.cpp mitkSurfaceEqualTest.cpp mitkSurfaceToSurfaceFilterTest.cpp mitkTimeGeometryTest.cpp mitkProportionalTimeGeometryTest.cpp mitkUndoControllerTest.cpp mitkVtkWidgetRenderingTest.cpp mitkVerboseLimitedLinearUndoTest.cpp mitkWeakPointerTest.cpp mitkTransferFunctionTest.cpp mitkStepperTest.cpp mitkRenderingManagerTest.cpp mitkCompositePixelValueToStringTest.cpp vtkMitkThickSlicesFilterTest.cpp mitkNodePredicateSourceTest.cpp mitkNodePredicateDataPropertyTest.cpp mitkVectorTest.cpp mitkClippedSurfaceBoundsCalculatorTest.cpp mitkExceptionTest.cpp mitkExtractSliceFilterTest.cpp mitkLogTest.cpp mitkImageDimensionConverterTest.cpp mitkLoggingAdapterTest.cpp mitkUIDGeneratorTest.cpp - mitkShaderRepositoryTest.cpp mitkPlanePositionManagerTest.cpp mitkAffineTransformBaseTest.cpp mitkPropertyAliasesTest.cpp mitkPropertyDescriptionsTest.cpp mitkPropertyExtensionsTest.cpp mitkPropertyFiltersTest.cpp mitkTinyXMLTest.cpp mitkRawImageFileReaderTest.cpp mitkInteractionEventTest.cpp mitkLookupTableTest.cpp mitkSTLFileReaderTest.cpp mitkPointTypeConversionTest.cpp mitkVectorTypeConversionTest.cpp mitkMatrixTypeConversionTest.cpp mitkArrayTypeConversionTest.cpp mitkSurfaceToImageFilterTest.cpp mitkBaseGeometryTest.cpp mitkImageToSurfaceFilterTest.cpp mitkEqualTest.cpp mitkLineTest.cpp mitkArbitraryTimeGeometryTest mitkItkImageIOTest.cpp mitkRotatedSlice4DTest.cpp mitkLevelWindowManagerCppUnitTest.cpp mitkVectorPropertyTest.cpp mitkTemporoSpatialStringPropertyTest.cpp mitkPropertyNameHelperTest.cpp mitkNodePredicateGeometryTest.cpp mitkPreferenceListReaderOptionsFunctorTest.cpp ) if(MITK_ENABLE_RENDERING_TESTING) set(MODULE_TESTS ${MODULE_TESTS} mitkPlaneGeometryDataMapper2DTest.cpp mitkPointSetDataInteractorTest.cpp #since mitkInteractionTestHelper is currently creating a vtkRenderWindow mitkSurfaceVtkMapper2DTest.cpp #new rendering test in CppUnit style mitkSurfaceVtkMapper2D3DTest.cpp # comparisons/consistency 2D/3D ) endif() # test with image filename as an extra command line parameter set(MODULE_IMAGE_TESTS mitkImageTimeSelectorTest.cpp #only runs on images mitkImageAccessorTest.cpp #only runs on images ) set(MODULE_SURFACE_TESTS mitkSurfaceVtkWriterTest.cpp #only runs on surfaces ) # list of images for which the tests are run set(MODULE_TESTIMAGE US4DCyl.nrrd Pic3D.nrrd Pic2DplusT.nrrd BallBinary30x30x30.nrrd Png2D-bw.png ) set(MODULE_TESTSURFACE binary.stl ball.stl ) set(MODULE_CUSTOM_TESTS mitkDataStorageTest.cpp mitkDicomSeriesReaderTest.cpp mitkDICOMLocaleTest.cpp mitkDataNodeTest.cpp mitkEventConfigTest.cpp mitkPointSetLocaleTest.cpp mitkImageTest.cpp mitkImageVtkMapper2DTest.cpp mitkImageVtkMapper2DLevelWindowTest.cpp mitkImageVtkMapper2DOpacityTest.cpp mitkImageVtkMapper2DResliceInterpolationPropertyTest.cpp mitkImageVtkMapper2DColorTest.cpp mitkImageVtkMapper2DSwivelTest.cpp mitkImageVtkMapper2DTransferFunctionTest.cpp mitkImageVtkMapper2DOpacityTransferFunctionTest.cpp mitkImageVtkMapper2DLookupTableTest.cpp mitkSurfaceVtkMapper3DTest mitkSurfaceVtkMapper3DTexturedSphereTest.cpp mitkVolumeCalculatorTest.cpp mitkLevelWindowManagerTest.cpp mitkPointSetVtkMapper2DTest.cpp mitkPointSetVtkMapper2DImageTest.cpp mitkPointSetVtkMapper2DGlyphTypeTest.cpp mitkPointSetVtkMapper2DTransformedPointsTest.cpp mitkVTKRenderWindowSizeTest.cpp mitkMultiComponentImageDataComparisonFilterTest.cpp mitkImageToItkTest.cpp mitkImageSliceSelectorTest.cpp mitkSurfaceDepthPeelingTest.cpp ) # Currently not working on windows because of a rendering timing issue # see bug 18083 for details if(NOT WIN32) set(MODULE_CUSTOM_TESTS ${MODULE_CUSTOM_TESTS} mitkSurfaceDepthSortingTest.cpp) endif() set(RESOURCE_FILES Interactions/AddAndRemovePoints.xml Interactions/globalConfig.xml Interactions/StatemachineTest.xml Interactions/StatemachineConfigTest.xml ) diff --git a/Modules/Core/test/mitkShaderRepositoryTest.cpp b/Modules/Core/test/mitkShaderRepositoryTest.cpp deleted file mode 100644 index 2a9ec98641..0000000000 --- a/Modules/Core/test/mitkShaderRepositoryTest.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/*=================================================================== - -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 "mitkIShaderRepository.h" - -#include "usGetModuleContext.h" -#include "usModuleContext.h" -#include "usServiceReference.h" - -#include "mitkTestingMacros.h" - -#include - -int mitkShaderRepositoryTest(int /*argc*/, char * /*argv*/ []) -{ - MITK_TEST_BEGIN("ShaderRepository") - - us::ModuleContext *context = us::GetModuleContext(); - us::ServiceReference serviceRef = context->GetServiceReference(); - MITK_TEST_CONDITION_REQUIRED(serviceRef, "IShaderRepository service ref") - - mitk::IShaderRepository *shaderRepo = context->GetService(serviceRef); - MITK_TEST_CONDITION_REQUIRED(shaderRepo, "Check non-empty IShaderRepositry") - - mitk::IShaderRepository::Shader::Pointer shader = shaderRepo->GetShader("mitkShaderLighting"); - MITK_TEST_CONDITION_REQUIRED(shader.IsNotNull(), "Non-null mitkShaderLighting shader") - - MITK_TEST_CONDITION(shader->GetName() == "mitkShaderLighting", "Shader name") - MITK_TEST_CONDITION(!shader->GetMaterialXml().empty(), "Shader content") - - const std::string testShader = - "" - "" - "" - "" - ""; - - const std::size_t shaderCount = shaderRepo->GetShaders().size(); - - std::stringstream testShaderStream(testShader); - const std::string testShaderName = "SmoothPlastic"; - int id = shaderRepo->LoadShader(testShaderStream, testShaderName); - MITK_TEST_CONDITION_REQUIRED(id > -1, "New shader id") - MITK_TEST_CONDITION(shaderRepo->GetShaders().size() == shaderCount + 1, "Shader count") - mitk::IShaderRepository::Shader::Pointer shader2 = shaderRepo->GetShader(testShaderName); - MITK_TEST_CONDITION_REQUIRED(shader2.IsNotNull(), "Non-null shader") - MITK_TEST_CONDITION(shader2->GetId() == id, "Shader id") - MITK_TEST_CONDITION(shader2->GetName() == testShaderName, "Shader name") - mitk::IShaderRepository::Shader::Pointer shader3 = shaderRepo->GetShader(id); - MITK_TEST_CONDITION_REQUIRED(shader3.IsNotNull(), "Non-null shader") - MITK_TEST_CONDITION(shader3->GetId() == id, "Shader id") - MITK_TEST_CONDITION(shader3->GetName() == testShaderName, "Shader name") - - MITK_TEST_CONDITION_REQUIRED(shaderRepo->UnloadShader(id), "Unload shader") - MITK_TEST_CONDITION(shaderRepo->GetShader(testShaderName).IsNull(), "Null shader") - MITK_TEST_CONDITION(shaderRepo->GetShader(id).IsNull(), "Null shader") - - MITK_TEST_END() -} diff --git a/Modules/DicomRT/src/mitkDoseImageVtkMapper2D.cpp b/Modules/DicomRT/src/mitkDoseImageVtkMapper2D.cpp index 4df91056d9..078253370d 100644 --- a/Modules/DicomRT/src/mitkDoseImageVtkMapper2D.cpp +++ b/Modules/DicomRT/src/mitkDoseImageVtkMapper2D.cpp @@ -1,1106 +1,1167 @@ /*=================================================================== 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. ===================================================================*/ -//MITK +// MITK +#include "mitkImageStatisticsHolder.h" +#include "mitkPlaneClipping.h" +#include "mitkPropertyNameHelper.h" #include #include #include #include #include #include #include #include #include #include #include +#include #include #include -#include #include #include -#include "mitkImageStatisticsHolder.h" -#include "mitkPlaneClipping.h" -#include "mitkPropertyNameHelper.h" -//MITK Rendering +// MITK Rendering #include "mitkDoseImageVtkMapper2D.h" -#include "vtkMitkThickSlicesFilter.h" #include "vtkMitkLevelWindowFilter.h" +#include "vtkMitkThickSlicesFilter.h" #include "vtkNeverTranslucentTexture.h" -//VTK +// VTK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -//ITK +// ITK #include mitk::DoseImageVtkMapper2D::DoseImageVtkMapper2D() { } mitk::DoseImageVtkMapper2D::~DoseImageVtkMapper2D() { - //The 3D RW Mapper (PlaneGeometryDataVtkMapper3D) is listening to this event, - //in order to delete the images from the 3D RW. - this->InvokeEvent( itk::DeleteEvent() ); + // The 3D RW Mapper (PlaneGeometryDataVtkMapper3D) is listening to this event, + // in order to delete the images from the 3D RW. + this->InvokeEvent(itk::DeleteEvent()); } -//set the two points defining the textured plane according to the dimension and spacing -void mitk::DoseImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, double planeBounds[6]) +// set the two points defining the textured plane according to the dimension and spacing +void mitk::DoseImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer *renderer, double planeBounds[6]) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); float depth = this->CalculateLayerDepth(renderer); - //Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct - //plane size in crosshair rotation and swivel mode. + // Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct + // plane size in crosshair rotation and swivel mode. localStorage->m_Plane->SetOrigin(planeBounds[0], planeBounds[2], depth); - //These two points define the axes of the plane in combination with the origin. - //Point 1 is the x-axis and point 2 the y-axis. - //Each plane is transformed according to the view (axial, coronal and saggital) afterwards. - localStorage->m_Plane->SetPoint1(planeBounds[1] , planeBounds[2], depth); //P1: (xMax, yMin, depth) - localStorage->m_Plane->SetPoint2(planeBounds[0], planeBounds[3], depth); //P2: (xMin, yMax, depth) + // These two points define the axes of the plane in combination with the origin. + // Point 1 is the x-axis and point 2 the y-axis. + // Each plane is transformed according to the view (axial, coronal and saggital) afterwards. + localStorage->m_Plane->SetPoint1(planeBounds[1], planeBounds[2], depth); // P1: (xMax, yMin, depth) + localStorage->m_Plane->SetPoint2(planeBounds[0], planeBounds[3], depth); // P2: (xMin, yMax, depth) } -float mitk::DoseImageVtkMapper2D::CalculateLayerDepth(mitk::BaseRenderer* renderer) +float mitk::DoseImageVtkMapper2D::CalculateLayerDepth(mitk::BaseRenderer *renderer) { - //get the clipping range to check how deep into z direction we can render images + // get the clipping range to check how deep into z direction we can render images double maxRange = renderer->GetVtkRenderer()->GetActiveCamera()->GetClippingRange()[1]; - //Due to a VTK bug, we cannot use the whole clipping range. /100 is empirically determined - float depth = -maxRange*0.01; // divide by 100 + // Due to a VTK bug, we cannot use the whole clipping range. /100 is empirically determined + float depth = -maxRange * 0.01; // divide by 100 int layer = 0; - GetDataNode()->GetIntProperty( "layer", layer, renderer); - //add the layer property for each image to render images with a higher layer on top of the others - depth += layer*10; //*10: keep some room for each image (e.g. for QBalls in between) - if(depth > 0.0f) { + GetDataNode()->GetIntProperty("layer", layer, renderer); + // add the layer property for each image to render images with a higher layer on top of the others + depth += layer * 10; //*10: keep some room for each image (e.g. for QBalls in between) + if (depth > 0.0f) + { depth = 0.0f; MITK_WARN << "Layer value exceeds clipping range. Set to minimum instead."; } return depth; } -const mitk::Image* mitk::DoseImageVtkMapper2D::GetInput( void ) +const mitk::Image *mitk::DoseImageVtkMapper2D::GetInput(void) { - return static_cast< const mitk::Image * >( GetDataNode()->GetData() ); + return static_cast(GetDataNode()->GetData()); } -vtkProp* mitk::DoseImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer* renderer) +vtkProp *mitk::DoseImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer *renderer) { - //return the actor corresponding to the renderer + // return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Actors; } -void mitk::DoseImageVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) +void mitk::DoseImageVtkMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { - LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); - mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); - mitk::DataNode* datanode = this->GetDataNode(); + mitk::Image *input = const_cast(this->GetInput()); + mitk::DataNode *datanode = this->GetDataNode(); - if ( input == nullptr || input->IsInitialized() == false ) + if (input == NULL || input->IsInitialized() == false) { return; } - //check if there is a valid worldGeometry + // check if there is a valid worldGeometry const PlaneGeometry *worldGeometry = renderer->GetCurrentWorldPlaneGeometry(); - if( ( worldGeometry == nullptr ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->HasReferenceGeometry() )) + if ((worldGeometry == NULL) || (!worldGeometry->IsValid()) || (!worldGeometry->HasReferenceGeometry())) { return; } input->Update(); // early out if there is no intersection of the current rendering geometry // and the geometry of the image that is to be rendered. - if ( !RenderingGeometryIntersectsImage( worldGeometry, input->GetSlicedGeometry() ) ) + if (!RenderingGeometryIntersectsImage(worldGeometry, input->GetSlicedGeometry())) { // set image to nullptr, to clear the texture in 3D, because // the latest image is used there if the plane is out of the geometry // see bug-13275 - localStorage->m_ReslicedImage = nullptr; - localStorage->m_Mapper->SetInputData( localStorage->m_EmptyPolyData ); + localStorage->m_ReslicedImage = NULL; + localStorage->m_Mapper->SetInputData(localStorage->m_EmptyPolyData); return; } - //set main input for ExtractSliceFilter + // set main input for ExtractSliceFilter localStorage->m_Reslicer->SetInput(input); localStorage->m_Reslicer->SetWorldGeometry(worldGeometry); - localStorage->m_Reslicer->SetTimeStep( this->GetTimestep() ); + localStorage->m_Reslicer->SetTimeStep(this->GetTimestep()); - //set the transformation of the image to adapt reslice axis - localStorage->m_Reslicer->SetResliceTransformByGeometry( input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() ) ); + // set the transformation of the image to adapt reslice axis + localStorage->m_Reslicer->SetResliceTransformByGeometry( + input->GetTimeGeometry()->GetGeometryForTimeStep(this->GetTimestep())); - //is the geometry of the slice based on the input image or the worldgeometry? + // is the geometry of the slice based on the input image or the worldgeometry? bool inPlaneResampleExtentByGeometry = false; datanode->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer); localStorage->m_Reslicer->SetInPlaneResampleExtentByGeometry(inPlaneResampleExtentByGeometry); // Initialize the interpolation mode for resampling; switch to nearest // neighbor if the input image is too small. - if ( (input->GetDimension() >= 3) && (input->GetDimension(2) > 1) ) + if ((input->GetDimension() >= 3) && (input->GetDimension(2) > 1)) { VtkResliceInterpolationProperty *resliceInterpolationProperty; - datanode->GetProperty( - resliceInterpolationProperty, "reslice interpolation" ); + datanode->GetProperty(resliceInterpolationProperty, "reslice interpolation"); int interpolationMode = VTK_RESLICE_NEAREST; - if ( resliceInterpolationProperty != nullptr ) + if (resliceInterpolationProperty != NULL) { interpolationMode = resliceInterpolationProperty->GetInterpolation(); } - switch ( interpolationMode ) + switch (interpolationMode) { - case VTK_RESLICE_NEAREST: - localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); - break; - case VTK_RESLICE_LINEAR: - localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_LINEAR); - break; - case VTK_RESLICE_CUBIC: - localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_CUBIC); - break; + case VTK_RESLICE_NEAREST: + localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); + break; + case VTK_RESLICE_LINEAR: + localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_LINEAR); + break; + case VTK_RESLICE_CUBIC: + localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_CUBIC); + break; } } else { localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); } - //set the vtk output property to true, makes sure that no unneeded mitk image convertion - //is done. + // set the vtk output property to true, makes sure that no unneeded mitk image convertion + // is done. localStorage->m_Reslicer->SetVtkOutputRequest(true); - //Thickslicing + // Thickslicing int thickSlicesMode = 0; int thickSlicesNum = 1; // Thick slices parameters - if( input->GetPixelType().GetNumberOfComponents() == 1 ) // for now only single component are allowed + if (input->GetPixelType().GetNumberOfComponents() == 1) // for now only single component are allowed { - DataNode *dn=renderer->GetCurrentWorldPlaneGeometryNode(); - if(dn) + DataNode *dn = renderer->GetCurrentWorldPlaneGeometryNode(); + if (dn) { - ResliceMethodProperty *resliceMethodEnumProperty=0; + ResliceMethodProperty *resliceMethodEnumProperty = 0; - if( dn->GetProperty( resliceMethodEnumProperty, "reslice.thickslices" ) && resliceMethodEnumProperty ) + if (dn->GetProperty(resliceMethodEnumProperty, "reslice.thickslices") && resliceMethodEnumProperty) thickSlicesMode = resliceMethodEnumProperty->GetValueAsId(); - IntProperty *intProperty=0; - if( dn->GetProperty( intProperty, "reslice.thickslices.num" ) && intProperty ) + IntProperty *intProperty = 0; + if (dn->GetProperty(intProperty, "reslice.thickslices.num") && intProperty) { thickSlicesNum = intProperty->GetValue(); - if(thickSlicesNum < 1) thickSlicesNum=1; - if(thickSlicesNum > 10) thickSlicesNum=10; + if (thickSlicesNum < 1) + thickSlicesNum = 1; + if (thickSlicesNum > 10) + thickSlicesNum = 10; } } else { MITK_WARN << "no associated widget plane data tree node found"; } } - const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( worldGeometry ); + const PlaneGeometry *planeGeometry = dynamic_cast(worldGeometry); - if(thickSlicesMode > 0) + if (thickSlicesMode > 0) { double dataZSpacing = 1.0; Vector3D normInIndex, normal; - if ( planeGeometry != nullptr ){ + if (planeGeometry != NULL) + { normal = planeGeometry->GetNormal(); - }else{ - const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(worldGeometry); - if(abstractGeometry != nullptr) + } + else + { + const mitk::AbstractTransformGeometry *abstractGeometry = + dynamic_cast(worldGeometry); + if (abstractGeometry != NULL) normal = abstractGeometry->GetPlane()->GetNormal(); else - return; //no fitting geometry set + return; // no fitting geometry set } normal.Normalize(); - input->GetTimeGeometry()->GetGeometryForTimeStep( this->GetTimestep() )->WorldToIndex( normal, normInIndex ); + input->GetTimeGeometry()->GetGeometryForTimeStep(this->GetTimestep())->WorldToIndex(normal, normInIndex); dataZSpacing = 1.0 / normInIndex.GetNorm(); - localStorage->m_Reslicer->SetOutputDimensionality( 3 ); + localStorage->m_Reslicer->SetOutputDimensionality(3); localStorage->m_Reslicer->SetOutputSpacingZDirection(dataZSpacing); - localStorage->m_Reslicer->SetOutputExtentZDirection( -thickSlicesNum, 0+thickSlicesNum ); + localStorage->m_Reslicer->SetOutputExtentZDirection(-thickSlicesNum, 0 + thickSlicesNum); // Do the reslicing. Modified() is called to make sure that the reslicer is // executed even though the input geometry information did not change; this // is necessary when the input /em data, but not the /em geometry changes. - localStorage->m_TSFilter->SetThickSliceMode( thickSlicesMode-1 ); - localStorage->m_TSFilter->SetInputData( localStorage->m_Reslicer->GetVtkOutput() ); + localStorage->m_TSFilter->SetThickSliceMode(thickSlicesMode - 1); + localStorage->m_TSFilter->SetInputData(localStorage->m_Reslicer->GetVtkOutput()); - //vtkFilter=>mitkFilter=>vtkFilter update mechanism will fail without calling manually + // vtkFilter=>mitkFilter=>vtkFilter update mechanism will fail without calling manually localStorage->m_Reslicer->Modified(); localStorage->m_Reslicer->Update(); localStorage->m_TSFilter->Modified(); localStorage->m_TSFilter->Update(); localStorage->m_ReslicedImage = localStorage->m_TSFilter->GetOutput(); } else { - //this is needed when thick mode was enable bevore. These variable have to be reset to default values - localStorage->m_Reslicer->SetOutputDimensionality( 2 ); + // this is needed when thick mode was enable bevore. These variable have to be reset to default values + localStorage->m_Reslicer->SetOutputDimensionality(2); localStorage->m_Reslicer->SetOutputSpacingZDirection(1.0); - localStorage->m_Reslicer->SetOutputExtentZDirection( 0, 0 ); - + localStorage->m_Reslicer->SetOutputExtentZDirection(0, 0); localStorage->m_Reslicer->Modified(); - //start the pipeline with updating the largest possible, needed if the geometry of the input has changed + // start the pipeline with updating the largest possible, needed if the geometry of the input has changed localStorage->m_Reslicer->UpdateLargestPossibleRegion(); localStorage->m_ReslicedImage = localStorage->m_Reslicer->GetVtkOutput(); } // Bounds information for reslicing (only reuqired if reference geometry // is present) - //this used for generating a vtkPLaneSource with the right size + // this used for generating a vtkPLaneSource with the right size double sliceBounds[6]; - for ( int i = 0; i < 6; ++i ) + for (int i = 0; i < 6; ++i) { sliceBounds[i] = 0.0; } localStorage->m_Reslicer->GetClippedPlaneBounds(sliceBounds); - //get the spacing of the slice + // get the spacing of the slice localStorage->m_mmPerPixel = localStorage->m_Reslicer->GetOutputSpacing(); // calculate minimum bounding rect of IMAGE in texture { double textureClippingBounds[6]; - for ( int i = 0; i < 6; ++i ) + for (int i = 0; i < 6; ++i) { textureClippingBounds[i] = 0.0; } // Calculate the actual bounds of the transformed plane clipped by the // dataset bounding box; this is required for drawing the texture at the // correct position during 3D mapping. - mitk::PlaneClipping::CalculateClippedPlaneBounds( input->GetGeometry(), planeGeometry, textureClippingBounds ); + mitk::PlaneClipping::CalculateClippedPlaneBounds(input->GetGeometry(), planeGeometry, textureClippingBounds); - textureClippingBounds[0] = static_cast< int >( textureClippingBounds[0] / localStorage->m_mmPerPixel[0] + 0.5 ); - textureClippingBounds[1] = static_cast< int >( textureClippingBounds[1] / localStorage->m_mmPerPixel[0] + 0.5 ); - textureClippingBounds[2] = static_cast< int >( textureClippingBounds[2] / localStorage->m_mmPerPixel[1] + 0.5 ); - textureClippingBounds[3] = static_cast< int >( textureClippingBounds[3] / localStorage->m_mmPerPixel[1] + 0.5 ); + textureClippingBounds[0] = static_cast(textureClippingBounds[0] / localStorage->m_mmPerPixel[0] + 0.5); + textureClippingBounds[1] = static_cast(textureClippingBounds[1] / localStorage->m_mmPerPixel[0] + 0.5); + textureClippingBounds[2] = static_cast(textureClippingBounds[2] / localStorage->m_mmPerPixel[1] + 0.5); + textureClippingBounds[3] = static_cast(textureClippingBounds[3] / localStorage->m_mmPerPixel[1] + 0.5); - //clipping bounds for cutting the image + // clipping bounds for cutting the image localStorage->m_LevelWindowFilter->SetClippingBounds(textureClippingBounds); } - //get the number of scalar components to distinguish between different image types + // get the number of scalar components to distinguish between different image types int numberOfComponents = localStorage->m_ReslicedImage->GetNumberOfScalarComponents(); - //get the showIsoLines property + // get the showIsoLines property bool showIsoLines = false; - datanode->GetBoolProperty( "dose.showIsoLines", showIsoLines, renderer ); + datanode->GetBoolProperty("dose.showIsoLines", showIsoLines, renderer); - if(showIsoLines) //contour rendering + if (showIsoLines) // contour rendering { - //generate contours/outlines + // generate contours/outlines localStorage->m_OutlinePolyData = CreateOutlinePolyData(renderer); float binaryOutlineWidth(1.0); - if ( datanode->GetFloatProperty( "outline width", binaryOutlineWidth, renderer ) ) + if (datanode->GetFloatProperty("outline width", binaryOutlineWidth, renderer)) { - if ( localStorage->m_Actors->GetNumberOfPaths() > 1 ) + if (localStorage->m_Actors->GetNumberOfPaths() > 1) { float binaryOutlineShadowWidth(1.5); - datanode->GetFloatProperty( "outline shadow width", binaryOutlineShadowWidth, renderer ); + datanode->GetFloatProperty("outline shadow width", binaryOutlineShadowWidth, renderer); - dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)) - ->GetProperty()->SetLineWidth( binaryOutlineWidth * binaryOutlineShadowWidth ); + dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)) + ->GetProperty() + ->SetLineWidth(binaryOutlineWidth * binaryOutlineShadowWidth); } - localStorage->m_Actor->GetProperty()->SetLineWidth( binaryOutlineWidth ); + localStorage->m_Actor->GetProperty()->SetLineWidth(binaryOutlineWidth); } } else { - localStorage->m_ReslicedImage = nullptr; - localStorage->m_Mapper->SetInputData( localStorage->m_EmptyPolyData ); + localStorage->m_ReslicedImage = NULL; + localStorage->m_Mapper->SetInputData(localStorage->m_EmptyPolyData); return; } - this->ApplyOpacity( renderer ); + this->ApplyOpacity(renderer); this->ApplyRenderingMode(renderer); // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter) localStorage->m_Texture->MapColorScalarsThroughLookupTableOff(); int displayedComponent = 0; if (datanode->GetIntProperty("Image.Displayed Component", displayedComponent, renderer) && numberOfComponents > 1) { localStorage->m_VectorComponentExtractor->SetComponents(displayedComponent); localStorage->m_VectorComponentExtractor->SetInputData(localStorage->m_ReslicedImage); localStorage->m_LevelWindowFilter->SetInputConnection(localStorage->m_VectorComponentExtractor->GetOutputPort(0)); } else { - //connect the input with the levelwindow filter + // connect the input with the levelwindow filter localStorage->m_LevelWindowFilter->SetInputData(localStorage->m_ReslicedImage); } // check for texture interpolation property bool textureInterpolation = false; - GetDataNode()->GetBoolProperty( "texture interpolation", textureInterpolation, renderer ); + GetDataNode()->GetBoolProperty("texture interpolation", textureInterpolation, renderer); - //set the interpolation modus according to the property + // set the interpolation modus according to the property localStorage->m_Texture->SetInterpolate(textureInterpolation); // connect the texture with the output of the levelwindow filter localStorage->m_Texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort()); - this->TransformActor( renderer ); + this->TransformActor(renderer); - vtkActor* contourShadowActor = dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0)); + vtkActor *contourShadowActor = dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)); - if(showIsoLines) //connect the mapper with the polyData which contains the lines + if (showIsoLines) // connect the mapper with the polyData which contains the lines { - //We need the contour for the binary outline property as actor + // We need the contour for the binary outline property as actor localStorage->m_Mapper->SetInputData(localStorage->m_OutlinePolyData); - localStorage->m_Actor->SetTexture(nullptr); //no texture for contours + localStorage->m_Actor->SetTexture(NULL); // no texture for contours - bool binaryOutlineShadow( false ); - datanode->GetBoolProperty( "outline binary shadow", binaryOutlineShadow, renderer ); + bool binaryOutlineShadow(false); + datanode->GetBoolProperty("outline binary shadow", binaryOutlineShadow, renderer); - if ( binaryOutlineShadow ) - contourShadowActor->SetVisibility( true ); + if (binaryOutlineShadow) + contourShadowActor->SetVisibility(true); else - contourShadowActor->SetVisibility( false ); + contourShadowActor->SetVisibility(false); } else - { //Connect the mapper with the input texture. This is the standard case. - //setup the textured plane - this->GeneratePlane( renderer, sliceBounds ); - //set the plane as input for the mapper + { // Connect the mapper with the input texture. This is the standard case. + // setup the textured plane + this->GeneratePlane(renderer, sliceBounds); + // set the plane as input for the mapper localStorage->m_Mapper->SetInputConnection(localStorage->m_Plane->GetOutputPort()); - //set the texture for the actor + // set the texture for the actor localStorage->m_Actor->SetTexture(localStorage->m_Texture); - contourShadowActor->SetVisibility( false ); + contourShadowActor->SetVisibility(false); } // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } void mitk::DoseImageVtkMapper2D::ApplyLevelWindow(mitk::BaseRenderer *renderer) { - LocalStorage *localStorage = this->GetLocalStorage( renderer ); + LocalStorage *localStorage = this->GetLocalStorage(renderer); LevelWindow levelWindow; - this->GetDataNode()->GetLevelWindow( levelWindow, renderer, "levelwindow" ); - localStorage->m_LevelWindowFilter->GetLookupTable()->SetRange( levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound() ); + this->GetDataNode()->GetLevelWindow(levelWindow, renderer, "levelwindow"); + localStorage->m_LevelWindowFilter->GetLookupTable()->SetRange(levelWindow.GetLowerWindowBound(), + levelWindow.GetUpperWindowBound()); mitk::LevelWindow opacLevelWindow; - if( this->GetDataNode()->GetLevelWindow( opacLevelWindow, renderer, "opaclevelwindow" ) ) + if (this->GetDataNode()->GetLevelWindow(opacLevelWindow, renderer, "opaclevelwindow")) { - //pass the opaque level window to the filter + // pass the opaque level window to the filter localStorage->m_LevelWindowFilter->SetMinOpacity(opacLevelWindow.GetLowerWindowBound()); localStorage->m_LevelWindowFilter->SetMaxOpacity(opacLevelWindow.GetUpperWindowBound()); } else { - //no opaque level window + // no opaque level window localStorage->m_LevelWindowFilter->SetMinOpacity(0.0); localStorage->m_LevelWindowFilter->SetMaxOpacity(255.0); } } -void mitk::DoseImageVtkMapper2D::ApplyColor( mitk::BaseRenderer* renderer ) +void mitk::DoseImageVtkMapper2D::ApplyColor(mitk::BaseRenderer *renderer) { - LocalStorage *localStorage = this->GetLocalStorage( renderer ); + LocalStorage *localStorage = this->GetLocalStorage(renderer); - float rgb[3]= { 1.0f, 1.0f, 1.0f }; + float rgb[3] = {1.0f, 1.0f, 1.0f}; // check for color prop and use it for rendering if it exists // binary image hovering & binary image selection - bool hover = false; + bool hover = false; bool selected = false; GetDataNode()->GetBoolProperty("binaryimage.ishovering", hover, renderer); GetDataNode()->GetBoolProperty("selected", selected, renderer); - if(hover && !selected) + if (hover && !selected) { - mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("binaryimage.hoveringcolor", renderer)); - if(colorprop.IsNotNull()) + mitk::ColorProperty::Pointer colorprop = + dynamic_cast(GetDataNode()->GetProperty("binaryimage.hoveringcolor", renderer)); + if (colorprop.IsNotNull()) { - memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); + memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3 * sizeof(float)); } else { - GetDataNode()->GetColor( rgb, renderer, "color" ); + GetDataNode()->GetColor(rgb, renderer, "color"); } } - if(selected) + if (selected) { - mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("binaryimage.selectedcolor", renderer)); - if(colorprop.IsNotNull()) { - memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); + mitk::ColorProperty::Pointer colorprop = + dynamic_cast(GetDataNode()->GetProperty("binaryimage.selectedcolor", renderer)); + if (colorprop.IsNotNull()) + { + memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3 * sizeof(float)); } else { GetDataNode()->GetColor(rgb, renderer, "color"); } } - if(!hover && !selected) + if (!hover && !selected) { - GetDataNode()->GetColor( rgb, renderer, "color" ); + GetDataNode()->GetColor(rgb, renderer, "color"); } - double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK - dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0))->GetProperty()->SetColor(rgbConv); + double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; // conversion to double for VTK + dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0))->GetProperty()->SetColor(rgbConv); localStorage->m_Actor->GetProperty()->SetColor(rgbConv); - if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 ) + if (localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1) { - float rgb[3]= { 1.0f, 1.0f, 1.0f }; - mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty - ("outline binary shadow color", renderer)); - if(colorprop.IsNotNull()) + float rgb[3] = {1.0f, 1.0f, 1.0f}; + mitk::ColorProperty::Pointer colorprop = + dynamic_cast(GetDataNode()->GetProperty("outline binary shadow color", renderer)); + if (colorprop.IsNotNull()) { - memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); + memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3 * sizeof(float)); } - double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK - dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetColor(rgbConv); + double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; // conversion to double for VTK + dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0))->GetProperty()->SetColor(rgbConv); } } -void mitk::DoseImageVtkMapper2D::ApplyOpacity( mitk::BaseRenderer* renderer ) +void mitk::DoseImageVtkMapper2D::ApplyOpacity(mitk::BaseRenderer *renderer) { - LocalStorage* localStorage = this->GetLocalStorage( renderer ); + LocalStorage *localStorage = this->GetLocalStorage(renderer); float opacity = 1.0f; // check for opacity prop and use it for rendering if it exists - GetDataNode()->GetOpacity( opacity, renderer, "opacity" ); - //set the opacity according to the properties + GetDataNode()->GetOpacity(opacity, renderer, "opacity"); + // set the opacity according to the properties localStorage->m_Actor->GetProperty()->SetOpacity(opacity); - if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 ) + if (localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1) { - dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetOpacity(opacity); + dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)) + ->GetProperty() + ->SetOpacity(opacity); } } -void mitk::DoseImageVtkMapper2D::ApplyRenderingMode( mitk::BaseRenderer* renderer ) +void mitk::DoseImageVtkMapper2D::ApplyRenderingMode(mitk::BaseRenderer *renderer) { - LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); + LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); bool binary = false; - this->GetDataNode()->GetBoolProperty( "binary", binary, renderer ); - if(binary) // is it a binary image? + this->GetDataNode()->GetBoolProperty("binary", binary, renderer); + if (binary) // is it a binary image? { - //for binary images, we always use our default LuT and map every value to (0,1) - //the opacity of 0 will always be 0.0. We never a apply a LuT/TfF nor a level window. + // for binary images, we always use our default LuT and map every value to (0,1) + // the opacity of 0 will always be 0.0. We never a apply a LuT/TfF nor a level window. localStorage->m_LevelWindowFilter->SetLookupTable(localStorage->m_BinaryLookupTable); } else { - //all other image types can make use of the rendering mode + // all other image types can make use of the rendering mode int renderingMode = mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR; - mitk::RenderingModeProperty::Pointer mode = dynamic_cast(this->GetDataNode()->GetProperty( "Image Rendering.Mode", renderer )); - if(mode.IsNotNull()) + mitk::RenderingModeProperty::Pointer mode = + dynamic_cast(this->GetDataNode()->GetProperty("Image Rendering.Mode", renderer)); + if (mode.IsNotNull()) { renderingMode = mode->GetRenderingMode(); } - switch(renderingMode) + switch (renderingMode) { - case mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR: - MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_LookupTable_Color"; - this->ApplyLookuptable( renderer ); - this->ApplyLevelWindow( renderer ); - break; - case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR: - MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_ColorTransferFunction_Color"; - this->ApplyColorTransferFunction( renderer ); - this->ApplyLevelWindow( renderer ); - break; - case mitk::RenderingModeProperty::LOOKUPTABLE_COLOR: - MITK_DEBUG << "'Image Rendering.Mode' = LookupTable_Color"; - this->ApplyLookuptable( renderer ); - break; - case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR: - MITK_DEBUG << "'Image Rendering.Mode' = ColorTransferFunction_Color"; - this->ApplyColorTransferFunction( renderer ); - break; - default: - MITK_ERROR << "No valid 'Image Rendering.Mode' set. Using LOOKUPTABLE_LEVELWINDOW_COLOR instead."; - this->ApplyLookuptable( renderer ); - this->ApplyLevelWindow( renderer ); - break; + case mitk::RenderingModeProperty::LOOKUPTABLE_LEVELWINDOW_COLOR: + MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_LookupTable_Color"; + this->ApplyLookuptable(renderer); + this->ApplyLevelWindow(renderer); + break; + case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_LEVELWINDOW_COLOR: + MITK_DEBUG << "'Image Rendering.Mode' = LevelWindow_ColorTransferFunction_Color"; + this->ApplyColorTransferFunction(renderer); + this->ApplyLevelWindow(renderer); + break; + case mitk::RenderingModeProperty::LOOKUPTABLE_COLOR: + MITK_DEBUG << "'Image Rendering.Mode' = LookupTable_Color"; + this->ApplyLookuptable(renderer); + break; + case mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR: + MITK_DEBUG << "'Image Rendering.Mode' = ColorTransferFunction_Color"; + this->ApplyColorTransferFunction(renderer); + break; + default: + MITK_ERROR << "No valid 'Image Rendering.Mode' set. Using LOOKUPTABLE_LEVELWINDOW_COLOR instead."; + this->ApplyLookuptable(renderer); + this->ApplyLevelWindow(renderer); + break; } } - //we apply color for all images (including binaries). - this->ApplyColor( renderer ); + // we apply color for all images (including binaries). + this->ApplyColor(renderer); } -void mitk::DoseImageVtkMapper2D::ApplyLookuptable( mitk::BaseRenderer* renderer ) +void mitk::DoseImageVtkMapper2D::ApplyLookuptable(mitk::BaseRenderer *renderer) { - LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); - vtkLookupTable* usedLookupTable = localStorage->m_ColorLookupTable; + LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); + vtkLookupTable *usedLookupTable = localStorage->m_ColorLookupTable; // If lookup table or transferfunction use is requested... - mitk::LookupTableProperty::Pointer lookupTableProp = dynamic_cast(this->GetDataNode()->GetProperty("LookupTable")); + mitk::LookupTableProperty::Pointer lookupTableProp = + dynamic_cast(this->GetDataNode()->GetProperty("LookupTable")); - if( lookupTableProp.IsNotNull() ) // is a lookuptable set? + if (lookupTableProp.IsNotNull()) // is a lookuptable set? { usedLookupTable = lookupTableProp->GetLookupTable()->GetVtkLookupTable(); } else { //"Image Rendering.Mode was set to use a lookup table but there is no property 'LookupTable'. - //A default (rainbow) lookup table will be used. - //Here have to do nothing. Warning for the user has been removed, due to unwanted console output - //in every interation of the rendering. + // A default (rainbow) lookup table will be used. + // Here have to do nothing. Warning for the user has been removed, due to unwanted console output + // in every interation of the rendering. } localStorage->m_LevelWindowFilter->SetLookupTable(usedLookupTable); } void mitk::DoseImageVtkMapper2D::ApplyColorTransferFunction(mitk::BaseRenderer *renderer) { - mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("Image Rendering.Transfer Function",renderer )); + mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast( + this->GetDataNode()->GetProperty("Image Rendering.Transfer Function", renderer)); - if( transferFunctionProp.IsNull() ) + if (transferFunctionProp.IsNull()) { - MITK_ERROR << "'Image Rendering.Mode'' was set to use a color transfer function but there is no property 'Image Rendering.Transfer Function'. Nothing will be done."; + MITK_ERROR << "'Image Rendering.Mode'' was set to use a color transfer function but there is no property 'Image " + "Rendering.Transfer Function'. Nothing will be done."; return; } - LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); - //pass the transfer function to our level window filter + LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); + // pass the transfer function to our level window filter localStorage->m_LevelWindowFilter->SetLookupTable(transferFunctionProp->GetValue()->GetColorTransferFunction()); } -void mitk::DoseImageVtkMapper2D::Update(mitk::BaseRenderer* renderer) +void mitk::DoseImageVtkMapper2D::Update(mitk::BaseRenderer *renderer) { - bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); - if ( !visible ) + if (!visible) { return; } - mitk::Image* data = const_cast( this->GetInput() ); - if ( data == nullptr ) + mitk::Image *data = const_cast(this->GetInput()); + if (data == NULL) { return; } // Calculate time step of the input data for the specified renderer (integer value) - this->CalculateTimeStep( renderer ); + this->CalculateTimeStep(renderer); // Check if time step is valid const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry(); - if ( ( dataTimeGeometry == nullptr ) - || ( dataTimeGeometry->CountTimeSteps() == 0 ) - || ( !dataTimeGeometry->IsValidTimeStep( this->GetTimestep() ) ) ) + if ((dataTimeGeometry == NULL) || (dataTimeGeometry->CountTimeSteps() == 0) || + (!dataTimeGeometry->IsValidTimeStep(this->GetTimestep()))) { return; } const DataNode *node = this->GetDataNode(); data->UpdateOutputInformation(); LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); - //check if something important has changed and we need to rerender - if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified? - || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified? - || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometryUpdateTime()) //was the geometry modified? - || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) - || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? - || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) + // check if something important has changed and we need to rerender + if ((localStorage->m_LastUpdateTime < node->GetMTime()) // was the node modified? + || + (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) // Was the data modified? + || + (localStorage->m_LastUpdateTime < + renderer->GetCurrentWorldPlaneGeometryUpdateTime()) // was the geometry modified? + || + (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) || + (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) // was a property modified? + || + (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime())) { - this->GenerateDataForRenderer( renderer ); + this->GenerateDataForRenderer(renderer); } // since we have checked that nothing important has changed, we can set // m_LastUpdateTime to the current time localStorage->m_LastUpdateTime.Modified(); } -void mitk::DoseImageVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) +void mitk::DoseImageVtkMapper2D::SetDefaultProperties(mitk::DataNode *node, + mitk::BaseRenderer *renderer, + bool overwrite) { - mitk::Image::Pointer image = dynamic_cast(node->GetData()); + mitk::Image::Pointer image = dynamic_cast(node->GetData()); // Properties common for both images and segmentations - node->AddProperty( "depthOffset", mitk::FloatProperty::New( 0.0 ), renderer, overwrite ); - node->AddProperty( "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ); - node->AddProperty( "outline width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); - node->AddProperty( "outline binary shadow", mitk::BoolProperty::New( false ), renderer, overwrite ); - node->AddProperty( "outline binary shadow color", ColorProperty::New(0.0,0.0,0.0), renderer, overwrite ); - node->AddProperty( "outline shadow width", mitk::FloatProperty::New( 1.5 ), renderer, overwrite ); - if(image->IsRotated()) node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC) ); - else node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ); - node->AddProperty( "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ); // set to user configurable default value (see global options) - node->AddProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ); - node->AddProperty( "bounding box", mitk::BoolProperty::New( false ) ); + node->AddProperty("depthOffset", mitk::FloatProperty::New(0.0), renderer, overwrite); + node->AddProperty("outline binary", mitk::BoolProperty::New(false), renderer, overwrite); + node->AddProperty("outline width", mitk::FloatProperty::New(1.0), renderer, overwrite); + node->AddProperty("outline binary shadow", mitk::BoolProperty::New(false), renderer, overwrite); + node->AddProperty("outline binary shadow color", ColorProperty::New(0.0, 0.0, 0.0), renderer, overwrite); + node->AddProperty("outline shadow width", mitk::FloatProperty::New(1.5), renderer, overwrite); + if (image->IsRotated()) + node->AddProperty("reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC)); + else + node->AddProperty("reslice interpolation", mitk::VtkResliceInterpolationProperty::New()); + node->AddProperty("texture interpolation", + mitk::BoolProperty::New(mitk::DataNodeFactory::m_TextureInterpolationActive)); // set to user + // configurable + // default value (see + // global options) + node->AddProperty("in plane resample extent by geometry", mitk::BoolProperty::New(false)); + node->AddProperty("bounding box", mitk::BoolProperty::New(false)); mitk::RenderingModeProperty::Pointer renderingModeProperty = mitk::RenderingModeProperty::New(); - node->AddProperty( "Image Rendering.Mode", renderingModeProperty); + node->AddProperty("Image Rendering.Mode", renderingModeProperty); // Set default grayscale look-up table mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); mitkLut->SetType(mitk::LookupTable::GRAYSCALE); mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty("LookupTable", mitkLutProp); std::string photometricInterpretation; // DICOM tag telling us how pixel values should be displayed - if ( node->GetStringProperty( "dicom.pixel.PhotometricInterpretation", photometricInterpretation ) ) + if (node->GetStringProperty("dicom.pixel.PhotometricInterpretation", photometricInterpretation)) { // modality provided by DICOM or other reader - if ( photometricInterpretation.find("MONOCHROME1") != std::string::npos ) // meaning: display MINIMUM pixels as WHITE + if (photometricInterpretation.find("MONOCHROME1") != std::string::npos) // meaning: display MINIMUM pixels as WHITE { // Set inverse grayscale look-up table mitkLut->SetType(mitk::LookupTable::INVERSE_GRAYSCALE); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty("LookupTable", mitkLutProp); } // Otherwise do nothing - the default grayscale look-up table has already been set } bool isBinaryImage(false); - if ( ! node->GetBoolProperty("binary", isBinaryImage) ) + if (!node->GetBoolProperty("binary", isBinaryImage)) { - // ok, property is not set, use heuristic to determine if this // is a binary image mitk::Image::Pointer centralSliceImage; ScalarType minValue = 0.0; ScalarType maxValue = 0.0; ScalarType min2ndValue = 0.0; ScalarType max2ndValue = 0.0; mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New(); sliceSelector->SetInput(image); - sliceSelector->SetSliceNr(image->GetDimension(2)/2); - sliceSelector->SetTimeNr(image->GetDimension(3)/2); - sliceSelector->SetChannelNr(image->GetDimension(4)/2); + sliceSelector->SetSliceNr(image->GetDimension(2) / 2); + sliceSelector->SetTimeNr(image->GetDimension(3) / 2); + sliceSelector->SetChannelNr(image->GetDimension(4) / 2); sliceSelector->Update(); centralSliceImage = sliceSelector->GetOutput(); - if ( centralSliceImage.IsNotNull() && centralSliceImage->IsInitialized() ) + if (centralSliceImage.IsNotNull() && centralSliceImage->IsInitialized()) { - minValue = centralSliceImage->GetStatistics()->GetScalarValueMin(); - maxValue = centralSliceImage->GetStatistics()->GetScalarValueMax(); + minValue = centralSliceImage->GetStatistics()->GetScalarValueMin(); + maxValue = centralSliceImage->GetStatistics()->GetScalarValueMax(); min2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMin(); max2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMax(); } if ((maxValue == min2ndValue && minValue == max2ndValue) || minValue == maxValue) { // centralSlice is strange, lets look at all data - minValue = image->GetStatistics()->GetScalarValueMin(); - maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute(); + minValue = image->GetStatistics()->GetScalarValueMin(); + maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute(); min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute(); max2ndValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute(); } - isBinaryImage = ( maxValue == min2ndValue && minValue == max2ndValue ); + isBinaryImage = (maxValue == min2ndValue && minValue == max2ndValue); } // some more properties specific for a binary... if (isBinaryImage) { - node->AddProperty( "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ); - node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); - node->AddProperty( "binaryimage.selectedcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); - node->AddProperty( "binaryimage.selectedannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); - node->AddProperty( "binaryimage.hoveringcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); - node->AddProperty( "binaryimage.hoveringannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); - node->AddProperty( "binary", mitk::BoolProperty::New( true ), renderer, overwrite ); + node->AddProperty("opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite); + node->AddProperty("color", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite); + node->AddProperty("binaryimage.selectedcolor", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite); + node->AddProperty("binaryimage.selectedannotationcolor", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite); + node->AddProperty("binaryimage.hoveringcolor", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite); + node->AddProperty("binaryimage.hoveringannotationcolor", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite); + node->AddProperty("binary", mitk::BoolProperty::New(true), renderer, overwrite); node->AddProperty("layer", mitk::IntProperty::New(10), renderer, overwrite); } - else //...or image type object + else //...or image type object { - node->AddProperty( "opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite ); - node->AddProperty( "color", ColorProperty::New(1.0,1.0,1.0), renderer, overwrite ); - node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite ); + node->AddProperty("opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite); + node->AddProperty("color", ColorProperty::New(1.0, 1.0, 1.0), renderer, overwrite); + node->AddProperty("binary", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("layer", mitk::IntProperty::New(0), renderer, overwrite); std::string className = image->GetNameOfClass(); if (className != "TensorImage" && className != "QBallImage") { PixelType pixelType = image->GetPixelType(); size_t numComponents = pixelType.GetNumberOfComponents(); - if ((pixelType.GetPixelTypeAsString() == "vector" && numComponents > 1) || numComponents == 2 || numComponents > 4) + if ((pixelType.GetPixelTypeAsString() == "vector" && numComponents > 1) || numComponents == 2 || + numComponents > 4) node->AddProperty("Image.Displayed Component", mitk::IntProperty::New(0), renderer, overwrite); } } - if(image.IsNotNull() && image->IsInitialized()) + if (image.IsNotNull() && image->IsInitialized()) { - if((overwrite) || (node->GetProperty("levelwindow", renderer)==nullptr)) + if ((overwrite) || (node->GetProperty("levelwindow", renderer) == NULL)) { /* initialize level/window from DICOM tags */ std::string sLevel; std::string sWindow; - if (GetBackwardsCompatibleDICOMProperty(0x0028, 0x1050, "dicom.voilut.WindowCenter", image->GetPropertyList(), sLevel) - && GetBackwardsCompatibleDICOMProperty(0x0028, 0x1051, "dicom.voilut.WindowWidth", image->GetPropertyList(), sWindow)) + if (GetBackwardsCompatibleDICOMProperty( + 0x0028, 0x1050, "dicom.voilut.WindowCenter", image->GetPropertyList(), sLevel) && + GetBackwardsCompatibleDICOMProperty( + 0x0028, 0x1051, "dicom.voilut.WindowWidth", image->GetPropertyList(), sWindow)) { - float level = atof( sLevel.c_str() ); - float window = atof( sWindow.c_str() ); + float level = atof(sLevel.c_str()); + float window = atof(sWindow.c_str()); mitk::LevelWindow contrast; std::string sSmallestPixelValueInSeries; std::string sLargestPixelValueInSeries; - if (GetBackwardsCompatibleDICOMProperty(0x0028, 0x0108, "dicom.series.SmallestPixelValueInSeries", image->GetPropertyList(), sSmallestPixelValueInSeries) - && GetBackwardsCompatibleDICOMProperty(0x0028, 0x0109, "dicom.series.LargestPixelValueInSeries", image->GetPropertyList(), sLargestPixelValueInSeries)) + if (GetBackwardsCompatibleDICOMProperty(0x0028, + 0x0108, + "dicom.series.SmallestPixelValueInSeries", + image->GetPropertyList(), + sSmallestPixelValueInSeries) && + GetBackwardsCompatibleDICOMProperty(0x0028, + 0x0109, + "dicom.series.LargestPixelValueInSeries", + image->GetPropertyList(), + sLargestPixelValueInSeries)) { - float smallestPixelValueInSeries = atof( sSmallestPixelValueInSeries.c_str() ); - float largestPixelValueInSeries = atof( sLargestPixelValueInSeries.c_str() ); - contrast.SetRangeMinMax( smallestPixelValueInSeries-1, largestPixelValueInSeries+1 ); // why not a little buffer? + float smallestPixelValueInSeries = atof(sSmallestPixelValueInSeries.c_str()); + float largestPixelValueInSeries = atof(sLargestPixelValueInSeries.c_str()); + contrast.SetRangeMinMax(smallestPixelValueInSeries - 1, + largestPixelValueInSeries + 1); // why not a little buffer? // might remedy some l/w widget challenges } else { - contrast.SetAuto( static_cast(node->GetData()), false, true ); // we need this as a fallback + contrast.SetAuto(static_cast(node->GetData()), false, true); // we need this as a fallback } - contrast.SetLevelWindow( level, window, true ); - node->SetProperty( "levelwindow", LevelWindowProperty::New( contrast ), renderer ); + contrast.SetLevelWindow(level, window, true); + node->SetProperty("levelwindow", LevelWindowProperty::New(contrast), renderer); } } - if(((overwrite) || (node->GetProperty("opaclevelwindow", renderer)==nullptr)) - && (image->GetPixelType().GetPixelType() == itk::ImageIOBase::RGBA) - && (image->GetPixelType().GetComponentType() == itk::ImageIOBase::UCHAR) ) + if (((overwrite) || (node->GetProperty("opaclevelwindow", renderer) == NULL)) && + (image->GetPixelType().GetPixelType() == itk::ImageIOBase::RGBA) && + (image->GetPixelType().GetComponentType() == itk::ImageIOBase::UCHAR)) { mitk::LevelWindow opaclevwin; - opaclevwin.SetRangeMinMax(0,255); - opaclevwin.SetWindowBounds(0,255); + opaclevwin.SetRangeMinMax(0, 255); + opaclevwin.SetWindowBounds(0, 255); mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); - node->SetProperty( "opaclevelwindow", prop, renderer ); + node->SetProperty("opaclevelwindow", prop, renderer); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } -mitk::DoseImageVtkMapper2D::LocalStorage* mitk::DoseImageVtkMapper2D::GetLocalStorage(mitk::BaseRenderer* renderer) +mitk::DoseImageVtkMapper2D::LocalStorage *mitk::DoseImageVtkMapper2D::GetLocalStorage(mitk::BaseRenderer *renderer) { return m_LSH.GetLocalStorage(renderer); } - -vtkSmartPointer mitk::DoseImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer* renderer ) +vtkSmartPointer mitk::DoseImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer *renderer) { - vtkSmartPointer points = vtkSmartPointer::New(); //the points to draw - vtkSmartPointer lines = vtkSmartPointer::New(); //the lines to connect the points + vtkSmartPointer points = vtkSmartPointer::New(); // the points to draw + vtkSmartPointer lines = vtkSmartPointer::New(); // the lines to connect the points vtkSmartPointer colors = vtkSmartPointer::New(); colors->SetNumberOfComponents(3); colors->SetName("Colors"); float pref; - this->GetDataNode()->GetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(),pref); + this->GetDataNode()->GetFloatProperty(mitk::RTConstants::REFERENCE_DOSE_PROPERTY_NAME.c_str(), pref); - mitk::IsoDoseLevelSetProperty::Pointer propIsoSet = dynamic_cast(GetDataNode()->GetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str())); + mitk::IsoDoseLevelSetProperty::Pointer propIsoSet = dynamic_cast( + GetDataNode()->GetProperty(mitk::RTConstants::DOSE_ISO_LEVELS_PROPERTY_NAME.c_str())); mitk::IsoDoseLevelSet::Pointer isoDoseLevelSet = propIsoSet->GetValue(); - for(mitk::IsoDoseLevelSet::ConstIterator doseIT = isoDoseLevelSet->Begin(); doseIT!=isoDoseLevelSet->End();++doseIT) + for (mitk::IsoDoseLevelSet::ConstIterator doseIT = isoDoseLevelSet->Begin(); doseIT != isoDoseLevelSet->End(); + ++doseIT) { - if(doseIT->GetVisibleIsoLine()) + if (doseIT->GetVisibleIsoLine()) { this->CreateLevelOutline(renderer, &(doseIT.Value()), pref, points, lines, colors); - }//end of if visible dose value - }//end of loop over all does values + } // end of if visible dose value + } // end of loop over all does values - mitk::IsoDoseLevelVectorProperty::Pointer propfreeIsoVec = dynamic_cast(GetDataNode()->GetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str())); + mitk::IsoDoseLevelVectorProperty::Pointer propfreeIsoVec = dynamic_cast( + GetDataNode()->GetProperty(mitk::RTConstants::DOSE_FREE_ISO_VALUES_PROPERTY_NAME.c_str())); mitk::IsoDoseLevelVector::Pointer frereIsoDoseLevelVec = propfreeIsoVec->GetValue(); - for(mitk::IsoDoseLevelVector::ConstIterator freeDoseIT = frereIsoDoseLevelVec->Begin(); freeDoseIT!=frereIsoDoseLevelVec->End();++freeDoseIT) + for (mitk::IsoDoseLevelVector::ConstIterator freeDoseIT = frereIsoDoseLevelVec->Begin(); + freeDoseIT != frereIsoDoseLevelVec->End(); + ++freeDoseIT) { - if(freeDoseIT->Value()->GetVisibleIsoLine()) + if (freeDoseIT->Value()->GetVisibleIsoLine()) { this->CreateLevelOutline(renderer, freeDoseIT->Value(), pref, points, lines, colors); - }//end of if visible dose value - }//end of loop over all does values + } // end of if visible dose value + } // end of loop over all does values // Create a polydata to store everything in vtkSmartPointer polyData = vtkSmartPointer::New(); // Add the points to the dataset polyData->SetPoints(points); // Add the lines to the dataset polyData->SetLines(lines); polyData->GetCellData()->SetScalars(colors); return polyData; } -void mitk::DoseImageVtkMapper2D::CreateLevelOutline(mitk::BaseRenderer* renderer, const mitk::IsoDoseLevel* level, float pref, vtkSmartPointer points, vtkSmartPointer lines, vtkSmartPointer colors) +void mitk::DoseImageVtkMapper2D::CreateLevelOutline(mitk::BaseRenderer *renderer, + const mitk::IsoDoseLevel *level, + float pref, + vtkSmartPointer points, + vtkSmartPointer lines, + vtkSmartPointer colors) { - LocalStorage* localStorage = this->GetLocalStorage(renderer); + LocalStorage *localStorage = this->GetLocalStorage(renderer); - //get the min and max index values of each direction - int* extent = localStorage->m_ReslicedImage->GetExtent(); + // get the min and max index values of each direction + int *extent = localStorage->m_ReslicedImage->GetExtent(); int xMin = extent[0]; int xMax = extent[1]; int yMin = extent[2]; int yMax = extent[3]; - int* dims = localStorage->m_ReslicedImage->GetDimensions(); //dimensions of the image - int line = dims[0]; //how many pixels per line? - //get the depth for each contour + int *dims = localStorage->m_ReslicedImage->GetDimensions(); // dimensions of the image + int line = dims[0]; // how many pixels per line? + // get the depth for each contour float depth = CalculateLayerDepth(renderer); - double doseValue = level->GetDoseValue()*pref; + double doseValue = level->GetDoseValue() * pref; mitk::IsoDoseLevel::ColorType isoColor = level->GetColor(); - unsigned char colorLine[3] = {static_cast(isoColor.GetRed()*255), - static_cast(isoColor.GetGreen()*255), - static_cast(isoColor.GetBlue()*255)}; + unsigned char colorLine[3] = {static_cast(isoColor.GetRed() * 255), + static_cast(isoColor.GetGreen() * 255), + static_cast(isoColor.GetBlue() * 255)}; - int x = xMin; //pixel index x - int y = yMin; //pixel index y - float* currentPixel; + int x = xMin; // pixel index x + int y = yMin; // pixel index y + float *currentPixel; // We take the pointer to the first pixel of the image - currentPixel = static_cast(localStorage->m_ReslicedImage->GetScalarPointer() ); + currentPixel = static_cast(localStorage->m_ReslicedImage->GetScalarPointer()); while (y <= yMax) { - //if the current pixel value is set to something + // if the current pixel value is set to something if ((currentPixel) && (*currentPixel >= doseValue)) { - //check in which direction a line is necessary - //a line is added if the neighbor of the current pixel has the value 0 - //and if the pixel is located at the edge of the image - - //if vvvvv not the first line vvvvv - if (y > yMin && *(currentPixel-line) < doseValue) - { //x direction - bottom edge of the pixel - //add the 2 points - vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); - vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); - //add the line between both points + // check in which direction a line is necessary + // a line is added if the neighbor of the current pixel has the value 0 + // and if the pixel is located at the edge of the image + + // if vvvvv not the first line vvvvv + if (y > yMin && *(currentPixel - line) < doseValue) + { // x direction - bottom edge of the pixel + // add the 2 points + vtkIdType p1 = + points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth); + vtkIdType p2 = + points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth); + // add the line between both points lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv not the last line vvvvv - if (y < yMax && *(currentPixel+line) < doseValue) - { //x direction - top edge of the pixel - vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); - vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); + // if vvvvv not the last line vvvvv + if (y < yMax && *(currentPixel + line) < doseValue) + { // x direction - top edge of the pixel + vtkIdType p1 = + points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth); + vtkIdType p2 = points->InsertNextPoint( + (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv not the first pixel vvvvv - if ( (x > xMin || y > yMin) && *(currentPixel-1) < doseValue) - { //y direction - left edge of the pixel - vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); - vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); + // if vvvvv not the first pixel vvvvv + if ((x > xMin || y > yMin) && *(currentPixel - 1) < doseValue) + { // y direction - left edge of the pixel + vtkIdType p1 = + points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth); + vtkIdType p2 = + points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv not the last pixel vvvvv - if ( (y < yMax || (x < xMax) ) && *(currentPixel+1) < doseValue) - { //y direction - right edge of the pixel - vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); - vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); + // if vvvvv not the last pixel vvvvv + if ((y < yMax || (x < xMax)) && *(currentPixel + 1) < doseValue) + { // y direction - right edge of the pixel + vtkIdType p1 = + points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth); + vtkIdType p2 = points->InsertNextPoint( + (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } /* now consider pixels at the edge of the image */ - //if vvvvv left edge of image vvvvv + // if vvvvv left edge of image vvvvv if (x == xMin) - { //draw left edge of the pixel - vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); - vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); + { // draw left edge of the pixel + vtkIdType p1 = + points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth); + vtkIdType p2 = + points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv right edge of image vvvvv + // if vvvvv right edge of image vvvvv if (x == xMax) - { //draw right edge of the pixel - vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); - vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); + { // draw right edge of the pixel + vtkIdType p1 = + points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth); + vtkIdType p2 = points->InsertNextPoint( + (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv bottom edge of image vvvvv + // if vvvvv bottom edge of image vvvvv if (y == yMin) - { //draw bottom edge of the pixel - vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); - vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); + { // draw bottom edge of the pixel + vtkIdType p1 = + points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth); + vtkIdType p2 = + points->InsertNextPoint((x + 1) * localStorage->m_mmPerPixel[0], y * localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - //if vvvvv top edge of image vvvvv + // if vvvvv top edge of image vvvvv if (y == yMax) - { //draw top edge of the pixel - vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); - vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); + { // draw top edge of the pixel + vtkIdType p1 = + points->InsertNextPoint(x * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth); + vtkIdType p2 = points->InsertNextPoint( + (x + 1) * localStorage->m_mmPerPixel[0], (y + 1) * localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); - colors->InsertNextTupleValue(colorLine); + colors->InsertNextTypedTuple(colorLine); } - }//end if currentpixel is set + } // end if currentpixel is set x++; if (x > xMax) - { //reached end of line + { // reached end of line x = xMin; y++; } // Increase the pointer-position to the next pixel. // This is safe, as the while-loop and the x-reset logic above makes // sure we do not exceed the bounds of the image currentPixel++; - }//end of while + } // end of while } -void mitk::DoseImageVtkMapper2D::TransformActor(mitk::BaseRenderer* renderer) +void mitk::DoseImageVtkMapper2D::TransformActor(mitk::BaseRenderer *renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); - //get the transformation matrix of the reslicer in order to render the slice as axial, coronal or saggital + // get the transformation matrix of the reslicer in order to render the slice as axial, coronal or saggital vtkSmartPointer trans = vtkSmartPointer::New(); vtkSmartPointer matrix = localStorage->m_Reslicer->GetResliceAxes(); trans->SetMatrix(matrix); - //transform the plane/contour (the actual actor) to the corresponding view (axial, coronal or saggital) + // transform the plane/contour (the actual actor) to the corresponding view (axial, coronal or saggital) localStorage->m_Actor->SetUserTransform(trans); - //transform the origin to center based coordinates, because MITK is center based. - localStorage->m_Actor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0); + // transform the origin to center based coordinates, because MITK is center based. + localStorage->m_Actor->SetPosition(-0.5 * localStorage->m_mmPerPixel[0], -0.5 * localStorage->m_mmPerPixel[1], 0.0); - if ( localStorage->m_Actors->GetNumberOfPaths() > 1 ) + if (localStorage->m_Actors->GetNumberOfPaths() > 1) { - vtkActor* secondaryActor = dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) ); + vtkActor *secondaryActor = dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)); secondaryActor->SetUserTransform(trans); - secondaryActor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0); + secondaryActor->SetPosition(-0.5 * localStorage->m_mmPerPixel[0], -0.5 * localStorage->m_mmPerPixel[1], 0.0); } } -bool mitk::DoseImageVtkMapper2D::RenderingGeometryIntersectsImage( const PlaneGeometry* renderingGeometry, SlicedGeometry3D* imageGeometry ) +bool mitk::DoseImageVtkMapper2D::RenderingGeometryIntersectsImage(const PlaneGeometry *renderingGeometry, + SlicedGeometry3D *imageGeometry) { // if either one of the two geometries is nullptr we return true // for safety reasons - if ( renderingGeometry == nullptr || imageGeometry == nullptr ) + if (renderingGeometry == NULL || imageGeometry == NULL) return true; // get the distance for the first cornerpoint - ScalarType initialDistance = renderingGeometry->SignedDistance( imageGeometry->GetCornerPoint( 0 ) ); - for( int i=1; i<8; i++ ) + ScalarType initialDistance = renderingGeometry->SignedDistance(imageGeometry->GetCornerPoint(0)); + for (int i = 1; i < 8; i++) { - mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint( i ); + mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint(i); // get the distance to the other cornerpoints - ScalarType distance = renderingGeometry->SignedDistance( cornerPoint ); + ScalarType distance = renderingGeometry->SignedDistance(cornerPoint); // if it has not the same signing as the distance of the first point - if ( initialDistance * distance < 0 ) + if (initialDistance * distance < 0) { // we have an intersection and return true return true; } } // all distances have the same sign, no intersection and we return false return false; } mitk::DoseImageVtkMapper2D::LocalStorage::~LocalStorage() { } mitk::DoseImageVtkMapper2D::LocalStorage::LocalStorage() -: m_VectorComponentExtractor(vtkSmartPointer::New()) + : m_VectorComponentExtractor(vtkSmartPointer::New()) { - m_LevelWindowFilter = vtkSmartPointer::New(); - //Do as much actions as possible in here to avoid double executions. + // Do as much actions as possible in here to avoid double executions. m_Plane = vtkSmartPointer::New(); m_Texture = vtkSmartPointer::New().GetPointer(); m_DefaultLookupTable = vtkSmartPointer::New(); m_BinaryLookupTable = vtkSmartPointer::New(); m_ColorLookupTable = vtkSmartPointer::New(); m_Mapper = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); m_Actors = vtkSmartPointer::New(); m_Reslicer = mitk::ExtractSliceFilter::New(); m_TSFilter = vtkSmartPointer::New(); m_OutlinePolyData = vtkSmartPointer::New(); m_ReslicedImage = vtkSmartPointer::New(); m_EmptyPolyData = vtkSmartPointer::New(); - //the following actions are always the same and thus can be performed - //in the constructor for each image (i.e. the image-corresponding local storage) + // the following actions are always the same and thus can be performed + // in the constructor for each image (i.e. the image-corresponding local storage) m_TSFilter->ReleaseDataFlagOn(); mitk::LookupTable::Pointer mitkLUT = mitk::LookupTable::New(); - //built a default lookuptable + // built a default lookuptable mitkLUT->SetType(mitk::LookupTable::GRAYSCALE); m_DefaultLookupTable = mitkLUT->GetVtkLookupTable(); mitkLUT->SetType(mitk::LookupTable::LEGACY_BINARY); m_BinaryLookupTable = mitkLUT->GetVtkLookupTable(); mitkLUT->SetType(mitk::LookupTable::LEGACY_RAINBOW_COLOR); m_ColorLookupTable = mitkLUT->GetVtkLookupTable(); - //do not repeat the texture (the image) + // do not repeat the texture (the image) m_Texture->RepeatOff(); - //set the mapper for the actor - m_Actor->SetMapper( m_Mapper ); + // set the mapper for the actor + m_Actor->SetMapper(m_Mapper); vtkSmartPointer outlineShadowActor = vtkSmartPointer::New(); - outlineShadowActor->SetMapper( m_Mapper ); + outlineShadowActor->SetMapper(m_Mapper); - m_Actors->AddPart( outlineShadowActor ); - m_Actors->AddPart( m_Actor ); + m_Actors->AddPart(outlineShadowActor); + m_Actors->AddPart(m_Actor); } diff --git a/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp b/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp index 8951458069..1c4de5612d 100644 --- a/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/src/Algorithms/mitkPartialVolumeAnalysisHistogramCalculator.cpp @@ -1,1271 +1,1270 @@ /*=================================================================== 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 "mitkPartialVolumeAnalysisHistogramCalculator.h" #include "mitkImageAccessByItk.h" #include "mitkExtractImageFilter.h" #include #include #include #include #include #include "itkResampleImageFilter.h" #include "itkGaussianInterpolateImageFunction.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "itkGaussianInterpolateImageFunction.h" #include "itkBSplineInterpolateImageFunction.h" #include "itkNearestNeighborInterpolateImageFunction.h" #include "itkImageMaskSpatialObject.h" #include "itkRegionOfInterestImageFilter.h" #include "itkListSample.h" #include "mitkAbstractTransformGeometry.h" #include #include -#include namespace mitk { PartialVolumeAnalysisHistogramCalculator::PartialVolumeAnalysisHistogramCalculator() : m_MaskingMode( MASKING_MODE_NONE ), m_MaskingModeChanged( false ), m_NumberOfBins(256), m_UpsamplingFactor(1), m_GaussianSigma(0), m_ForceUpdate(false), m_PlanarFigureThickness(0) { m_EmptyHistogram = HistogramType::New(); m_EmptyHistogram->SetMeasurementVectorSize(1); HistogramType::SizeType histogramSize(1); histogramSize.Fill( 256 ); m_EmptyHistogram->Initialize( histogramSize ); m_EmptyStatistics.Reset(); } PartialVolumeAnalysisHistogramCalculator::~PartialVolumeAnalysisHistogramCalculator() { } void PartialVolumeAnalysisHistogramCalculator::SetImage( const mitk::Image *image ) { if ( m_Image != image ) { m_Image = image; this->Modified(); m_ImageStatisticsTimeStamp.Modified(); m_ImageStatisticsCalculationTriggerBool = true; } } void PartialVolumeAnalysisHistogramCalculator::AddAdditionalResamplingImage( const mitk::Image *image ) { m_AdditionalResamplingImages.push_back(image); this->Modified(); m_ImageStatisticsTimeStamp.Modified(); m_ImageStatisticsCalculationTriggerBool = true; } void PartialVolumeAnalysisHistogramCalculator::SetModified( ) { this->Modified(); m_ImageStatisticsTimeStamp.Modified(); m_ImageStatisticsCalculationTriggerBool = true; m_MaskedImageStatisticsTimeStamp.Modified(); m_MaskedImageStatisticsCalculationTriggerBool = true; m_PlanarFigureStatisticsTimeStamp.Modified(); m_PlanarFigureStatisticsCalculationTriggerBool = true; } void PartialVolumeAnalysisHistogramCalculator::SetImageMask( const mitk::Image *imageMask ) { if ( m_Image.IsNull() ) { itkExceptionMacro( << "Image needs to be set first!" ); } if ( m_Image->GetTimeSteps() != imageMask->GetTimeSteps() ) { itkExceptionMacro( << "Image and image mask need to have equal number of time steps!" ); } if ( m_ImageMask != imageMask ) { m_ImageMask = imageMask; this->Modified(); m_MaskedImageStatisticsTimeStamp.Modified(); m_MaskedImageStatisticsCalculationTriggerBool = true; } } void PartialVolumeAnalysisHistogramCalculator::SetPlanarFigure( const mitk::PlanarFigure *planarFigure ) { if ( m_Image.IsNull() ) { itkExceptionMacro( << "Image needs to be set first!" ); } if ( m_PlanarFigure != planarFigure ) { m_PlanarFigure = planarFigure; this->Modified(); m_PlanarFigureStatisticsTimeStamp.Modified(); m_PlanarFigureStatisticsCalculationTriggerBool = true; } } void PartialVolumeAnalysisHistogramCalculator::SetMaskingMode( unsigned int mode ) { if ( m_MaskingMode != mode ) { m_MaskingMode = mode; m_MaskingModeChanged = true; this->Modified(); } } void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToNone() { if ( m_MaskingMode != MASKING_MODE_NONE ) { m_MaskingMode = MASKING_MODE_NONE; m_MaskingModeChanged = true; this->Modified(); } } void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToImage() { if ( m_MaskingMode != MASKING_MODE_IMAGE ) { m_MaskingMode = MASKING_MODE_IMAGE; m_MaskingModeChanged = true; this->Modified(); } } void PartialVolumeAnalysisHistogramCalculator::SetMaskingModeToPlanarFigure() { if ( m_MaskingMode != MASKING_MODE_PLANARFIGURE ) { m_MaskingMode = MASKING_MODE_PLANARFIGURE; m_MaskingModeChanged = true; this->Modified(); } } bool PartialVolumeAnalysisHistogramCalculator::ComputeStatistics() { MITK_DEBUG << "ComputeStatistics() start"; if ( m_Image.IsNull() ) { itkExceptionMacro( << "Image not set!" ); } if ( m_Image->GetReferenceCount() == 1 ) { MITK_DEBUG << "No Stats calculated; no one else holds a reference on it"; return false; } // If a mask was set but we are the only ones to still hold a reference on // it, delete it. if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() == 1) ) { m_ImageMask = nullptr; } // Check if statistics is already up-to-date unsigned long imageMTime = m_ImageStatisticsTimeStamp.GetMTime(); unsigned long maskedImageMTime = m_MaskedImageStatisticsTimeStamp.GetMTime(); unsigned long planarFigureMTime = m_PlanarFigureStatisticsTimeStamp.GetMTime(); bool imageStatisticsCalculationTrigger = m_ImageStatisticsCalculationTriggerBool; bool maskedImageStatisticsCalculationTrigger = m_MaskedImageStatisticsCalculationTriggerBool; bool planarFigureStatisticsCalculationTrigger = m_PlanarFigureStatisticsCalculationTriggerBool; if ( /*prevent calculation without mask*/!m_ForceUpdate &&( m_MaskingMode == MASKING_MODE_NONE || ( ((m_MaskingMode != MASKING_MODE_NONE) || (imageMTime > m_Image->GetMTime() && !imageStatisticsCalculationTrigger)) && ((m_MaskingMode != MASKING_MODE_IMAGE) || (m_ImageMask.IsNotNull() && maskedImageMTime > m_ImageMask->GetMTime() && !maskedImageStatisticsCalculationTrigger)) && ((m_MaskingMode != MASKING_MODE_PLANARFIGURE) || (m_PlanarFigure.IsNotNull() && planarFigureMTime > m_PlanarFigure->GetMTime() && !planarFigureStatisticsCalculationTrigger)) ) ) ) { MITK_DEBUG << "Returning, statistics already up to date!"; if ( m_MaskingModeChanged ) { m_MaskingModeChanged = false; return true; } else { return false; } } // Reset state changed flag m_MaskingModeChanged = false; // Depending on masking mode, extract and/or generate the required image // and mask data from the user input this->ExtractImageAndMask( ); Statistics *statistics; HistogramType::ConstPointer *histogram; switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: statistics = &m_ImageStatistics; histogram = &m_ImageHistogram; m_ImageStatisticsTimeStamp.Modified(); m_ImageStatisticsCalculationTriggerBool = false; break; case MASKING_MODE_IMAGE: statistics = &m_MaskedImageStatistics; histogram = &m_MaskedImageHistogram; m_MaskedImageStatisticsTimeStamp.Modified(); m_MaskedImageStatisticsCalculationTriggerBool = false; break; case MASKING_MODE_PLANARFIGURE: statistics = &m_PlanarFigureStatistics; histogram = &m_PlanarFigureHistogram; m_PlanarFigureStatisticsTimeStamp.Modified(); m_PlanarFigureStatisticsCalculationTriggerBool = false; break; } // Calculate statistics and histogram(s) if ( m_InternalImage->GetDimension() == 3 ) { if ( m_MaskingMode == MASKING_MODE_NONE ) { // Reset state changed flag AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateStatisticsUnmasked, 3, *statistics, histogram ); } else { AccessFixedDimensionByItk_3( m_InternalImage, InternalCalculateStatisticsMasked, 3, m_InternalImageMask3D.GetPointer(), *statistics, histogram ); } } else if ( m_InternalImage->GetDimension() == 2 ) { if ( m_MaskingMode == MASKING_MODE_NONE ) { AccessFixedDimensionByItk_2( m_InternalImage, InternalCalculateStatisticsUnmasked, 2, *statistics, histogram ); } else { AccessFixedDimensionByItk_3( m_InternalImage, InternalCalculateStatisticsMasked, 2, m_InternalImageMask2D.GetPointer(), *statistics, histogram ); } } else { MITK_ERROR << "ImageStatistics: Image dimension not supported!"; } // Release unused image smart pointers to free memory // m_InternalImage = mitk::Image::Pointer(); m_InternalImageMask3D = MaskImage3DType::Pointer(); m_InternalImageMask2D = MaskImage2DType::Pointer(); return true; } const PartialVolumeAnalysisHistogramCalculator::HistogramType * PartialVolumeAnalysisHistogramCalculator::GetHistogram( ) const { if ( m_Image.IsNull() ) { return nullptr; } switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: return m_ImageHistogram; case MASKING_MODE_IMAGE: return m_MaskedImageHistogram; case MASKING_MODE_PLANARFIGURE: return m_PlanarFigureHistogram; } } const PartialVolumeAnalysisHistogramCalculator::Statistics & PartialVolumeAnalysisHistogramCalculator::GetStatistics( ) const { if ( m_Image.IsNull() ) { return m_EmptyStatistics; } switch ( m_MaskingMode ) { case MASKING_MODE_NONE: default: return m_ImageStatistics; case MASKING_MODE_IMAGE: return m_MaskedImageStatistics; case MASKING_MODE_PLANARFIGURE: return m_PlanarFigureStatistics; } } void PartialVolumeAnalysisHistogramCalculator::ExtractImageAndMask( ) { MITK_DEBUG << "ExtractImageAndMask( ) start"; if ( m_Image.IsNull() ) { throw std::runtime_error( "Error: image empty!" ); } mitk::Image *timeSliceImage = const_cast(m_Image.GetPointer());//imageTimeSelector->GetOutput(); switch ( m_MaskingMode ) { case MASKING_MODE_NONE: { m_InternalImage = timeSliceImage; int s = m_AdditionalResamplingImages.size(); m_InternalAdditionalResamplingImages.resize(s); for(int i=0; i(m_AdditionalResamplingImages[i].GetPointer()); } m_InternalImageMask2D = nullptr; m_InternalImageMask3D = nullptr; break; } case MASKING_MODE_IMAGE: { if ( m_ImageMask.IsNotNull() && (m_ImageMask->GetReferenceCount() > 1) ) { ImageTimeSelector::Pointer maskedImageTimeSelector = ImageTimeSelector::New(); maskedImageTimeSelector->SetInput( m_ImageMask ); maskedImageTimeSelector->SetTimeNr( 0 ); maskedImageTimeSelector->UpdateLargestPossibleRegion(); mitk::Image *timeSliceMaskedImage = maskedImageTimeSelector->GetOutput(); InternalMaskImage(timeSliceMaskedImage); if(m_UpsamplingFactor != 1) { InternalResampleImage(m_InternalImageMask3D); } AccessFixedDimensionByItk_1( timeSliceImage, InternalResampleImageFromMask, 3, -1 ); int s = m_AdditionalResamplingImages.size(); m_InternalAdditionalResamplingImages.resize(s); for(int i=0; iIsClosed() ) { throw std::runtime_error( "Masking not possible for non-closed figures" ); } const BaseGeometry *imageGeometry = timeSliceImage->GetUpdatedGeometry(); if ( imageGeometry == nullptr ) { throw std::runtime_error( "Image geometry invalid!" ); } const PlaneGeometry *planarFigureGeometry2D = m_PlanarFigure->GetPlaneGeometry(); if ( planarFigureGeometry2D == nullptr ) { throw std::runtime_error( "Planar-Figure not yet initialized!" ); } const PlaneGeometry *planarFigureGeometry = dynamic_cast< const PlaneGeometry * >( planarFigureGeometry2D ); const AbstractTransformGeometry *abstrTransfGeometry = dynamic_cast< const AbstractTransformGeometry * >( planarFigureGeometry2D ); if ( !planarFigureGeometry || abstrTransfGeometry ) { throw std::runtime_error( "Only PlaneGeometry supported." ); } // unsigned int axis = 2; // unsigned int slice = 0; AccessFixedDimensionByItk_3( timeSliceImage, InternalReorientImagePlane, 3, timeSliceImage->GetGeometry(), m_PlanarFigure->GetGeometry(), -1 ); AccessFixedDimensionByItk_1( m_InternalImage, InternalCalculateMaskFromPlanarFigure, 3, 2 ); int s = m_AdditionalResamplingImages.size(); for(int i=0; iGetGeometry(), m_PlanarFigure->GetGeometry(), i ); AccessFixedDimensionByItk_1( m_InternalAdditionalResamplingImages[i], InternalCropAdditionalImage, 3, i ); } } } } bool PartialVolumeAnalysisHistogramCalculator::GetPrincipalAxis( const Geometry3D *geometry, Vector3D vector, unsigned int &axis ) { vector.Normalize(); for ( unsigned int i = 0; i < 3; ++i ) { Vector3D axisVector = geometry->GetAxisVector( i ); axisVector.Normalize(); if ( fabs( fabs( axisVector * vector ) - 1.0) < mitk::eps ) { axis = i; return true; } } return false; } void PartialVolumeAnalysisHistogramCalculator::InternalMaskImage( mitk::Image *image ) { typedef itk::ImageMaskSpatialObject<3> ImageMaskSpatialObject; typedef itk::Image< unsigned char, 3 > ImageType; typedef mitk::ImageToItk CastType; CastType::Pointer caster = CastType::New(); caster->SetInput(image); caster->Update(); ImageMaskSpatialObject::Pointer maskSO = ImageMaskSpatialObject::New(); maskSO->SetImage ( caster->GetOutput() ); m_InternalMask3D = maskSO->GetAxisAlignedBoundingBoxRegion(); // check if bounding box is empty, if so set it to 1,1,1 // to prevent empty mask image if (m_InternalMask3D.GetSize()[0] == 0 ) { m_InternalMask3D.SetSize(0,1); m_InternalMask3D.SetSize(1,1); m_InternalMask3D.SetSize(2,1); } MITK_DEBUG << "Bounding Box Region: " << m_InternalMask3D; // crop the mask image to the BoundingBoxRegion extracted via the spatial masking object typedef itk::RegionOfInterestImageFilter< ImageType, MaskImage3DType > ROIFilterType; ROIFilterType::Pointer roi = ROIFilterType::New(); roi->SetRegionOfInterest(m_InternalMask3D); roi->SetInput(caster->GetOutput()); roi->Update(); m_InternalImageMask3D = roi->GetOutput(); MITK_DEBUG << "Created m_InternalImageMask3D"; } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalReorientImagePlane( const itk::Image< TPixel, VImageDimension > *image, mitk::BaseGeometry* , mitk::BaseGeometry* planegeo3D, int additionalIndex ) { MITK_DEBUG << "InternalReorientImagePlane() start"; typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< float, VImageDimension > FloatImageType; typedef itk::ResampleImageFilter ResamplerType; typename ResamplerType::Pointer resampler = ResamplerType::New(); mitk::PlaneGeometry* planegeo = dynamic_cast(planegeo3D); if ( !planegeo ) { throw std::runtime_error( "Unexpected null pointer returned for pointer to PlaneGeometry." ); } else { mitk::AbstractTransformGeometry* abstrGeo = dynamic_cast(planegeo3D); if ( abstrGeo ) { throw std::runtime_error( "Unexpected pointer to AbstractTransformGeometry returned." ); } } float upsamp = m_UpsamplingFactor; float gausssigma = m_GaussianSigma; // Spacing typename ResamplerType::SpacingType spacing = planegeo->GetSpacing(); spacing[0] = image->GetSpacing()[0] / upsamp; spacing[1] = image->GetSpacing()[1] / upsamp; spacing[2] = image->GetSpacing()[2]; if(m_PlanarFigureThickness) { spacing[2] = image->GetSpacing()[2] / upsamp; } resampler->SetOutputSpacing( spacing ); // Size typename ResamplerType::SizeType size; size[0] = planegeo->GetExtentInMM(0) / spacing[0]; size[1] = planegeo->GetExtentInMM(1) / spacing[1]; size[2] = 1+2*m_PlanarFigureThickness; // klaus add +2*m_PlanarFigureThickness MITK_DEBUG << "setting size2:="<SetSize( size ); // Origin typename mitk::Point3D orig = planegeo->GetOrigin(); typename mitk::Point3D corrorig; planegeo3D->WorldToIndex(orig,corrorig); corrorig[0] += 0.5/upsamp; corrorig[1] += 0.5/upsamp; if(m_PlanarFigureThickness) { float thickyyy = m_PlanarFigureThickness; thickyyy/=upsamp; corrorig[2] -= thickyyy; // klaus add -= (float)m_PlanarFigureThickness/upsamp statt += 0 } planegeo3D->IndexToWorld(corrorig,corrorig); resampler->SetOutputOrigin(corrorig ); // Direction typename ResamplerType::DirectionType direction; typename mitk::AffineTransform3D::MatrixType matrix = planegeo->GetIndexToWorldTransform()->GetMatrix(); for(unsigned int c = 0; c < matrix.ColumnDimensions; ++c) { double sum = 0; for(unsigned int r = 0 ; rSetOutputDirection( direction ); // Gaussian interpolation if(gausssigma != 0) { double sigma[3]; for( unsigned int d = 0; d < 3; d++ ) { sigma[d] = gausssigma * image->GetSpacing()[d]; } double alpha = 2.0; typedef itk::GaussianInterpolateImageFunction GaussianInterpolatorType; typename GaussianInterpolatorType::Pointer interpolator = GaussianInterpolatorType::New(); interpolator->SetInputImage( image ); interpolator->SetParameters( sigma, alpha ); resampler->SetInterpolator( interpolator ); } else { - // typedef typename itk::BSplineInterpolateImageFunction - // InterpolatorType; + // typedef typename itk::BSplineInterpolateImageFunction + // InterpolatorType; typedef typename itk::LinearInterpolateImageFunction InterpolatorType; typename InterpolatorType::Pointer interpolator = InterpolatorType::New(); interpolator->SetInputImage( image ); resampler->SetInterpolator( interpolator ); } // Other resampling options resampler->SetInput( image ); resampler->SetDefaultPixelValue(0); MITK_DEBUG << "Resampling requested image plane ... "; resampler->Update(); MITK_DEBUG << " ... done"; if(additionalIndex < 0) { this->m_InternalImage = mitk::Image::New(); this->m_InternalImage->InitializeByItk( resampler->GetOutput() ); this->m_InternalImage->SetVolume( resampler->GetOutput()->GetBufferPointer() ); } else { unsigned int myIndex = additionalIndex; this->m_InternalAdditionalResamplingImages.push_back(mitk::Image::New()); this->m_InternalAdditionalResamplingImages[myIndex]->InitializeByItk( resampler->GetOutput() ); this->m_InternalAdditionalResamplingImages[myIndex]->SetVolume( resampler->GetOutput()->GetBufferPointer() ); } } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalResampleImageFromMask( const itk::Image< TPixel, VImageDimension > *image, int additionalIndex ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typename ImageType::Pointer outImage = ImageType::New(); outImage->SetSpacing( m_InternalImageMask3D->GetSpacing() ); // Set the image spacing outImage->SetOrigin( m_InternalImageMask3D->GetOrigin() ); // Set the image origin outImage->SetDirection( m_InternalImageMask3D->GetDirection() ); // Set the image direction outImage->SetRegions( m_InternalImageMask3D->GetLargestPossibleRegion() ); outImage->Allocate(); outImage->FillBuffer(0); typedef itk::InterpolateImageFunction BaseInterpType; typedef itk::GaussianInterpolateImageFunction GaussianInterpolatorType; typedef itk::LinearInterpolateImageFunction LinearInterpolatorType; typename BaseInterpType::Pointer interpolator; if(m_GaussianSigma != 0) { double sigma[3]; for( unsigned int d = 0; d < 3; d++ ) { sigma[d] = m_GaussianSigma * image->GetSpacing()[d]; } double alpha = 2.0; interpolator = GaussianInterpolatorType::New(); dynamic_cast(interpolator.GetPointer())->SetParameters( sigma, alpha ); } else { interpolator = LinearInterpolatorType::New(); } interpolator->SetInputImage( image ); itk::ImageRegionConstIterator itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion()); itk::ImageRegionIterator itimage(outImage, outImage->GetLargestPossibleRegion()); itmask.GoToBegin(); itimage.GoToBegin(); itk::Point< double, 3 > point; itk::ContinuousIndex< double, 3 > index; while( !itmask.IsAtEnd() ) { if(itmask.Get() != 0) { outImage->TransformIndexToPhysicalPoint (itimage.GetIndex(), point); image->TransformPhysicalPointToContinuousIndex(point, index); itimage.Set(interpolator->EvaluateAtContinuousIndex(index)); } ++itmask; ++itimage; } if(additionalIndex < 0) { this->m_InternalImage = mitk::Image::New(); this->m_InternalImage->InitializeByItk( outImage.GetPointer() ); this->m_InternalImage->SetVolume( outImage->GetBufferPointer() ); } else { this->m_InternalAdditionalResamplingImages[additionalIndex] = mitk::Image::New(); this->m_InternalAdditionalResamplingImages[additionalIndex]->InitializeByItk( outImage.GetPointer() ); this->m_InternalAdditionalResamplingImages[additionalIndex]->SetVolume( outImage->GetBufferPointer() ); } } void PartialVolumeAnalysisHistogramCalculator::InternalResampleImage( const MaskImage3DType *image ) { typedef itk::ResampleImageFilter ResamplerType; ResamplerType::Pointer resampler = ResamplerType::New(); // Size ResamplerType::SizeType size; size[0] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[0]; size[1] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[1]; size[2] = m_UpsamplingFactor * image->GetLargestPossibleRegion().GetSize()[2];; resampler->SetSize( size ); // Origin mitk::Point3D orig = image->GetOrigin(); resampler->SetOutputOrigin(orig ); // Spacing ResamplerType::SpacingType spacing; spacing[0] = image->GetSpacing()[0] / m_UpsamplingFactor; spacing[1] = image->GetSpacing()[1] / m_UpsamplingFactor; spacing[2] = image->GetSpacing()[2] / m_UpsamplingFactor; resampler->SetOutputSpacing( spacing ); resampler->SetOutputDirection( image->GetDirection() ); typedef itk::NearestNeighborInterpolateImageFunction InterpolatorType; InterpolatorType::Pointer interpolator = InterpolatorType::New(); interpolator->SetInputImage( image ); resampler->SetInterpolator( interpolator ); // Other resampling options resampler->SetInput( image ); resampler->SetDefaultPixelValue(0); resampler->Update(); m_InternalImageMask3D = resampler->GetOutput(); } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalCalculateStatisticsUnmasked( const itk::Image< TPixel, VImageDimension > *image, Statistics &statistics, typename HistogramType::ConstPointer *histogram ) { MITK_DEBUG << "InternalCalculateStatisticsUnmasked()"; typedef itk::Image< TPixel, VImageDimension > ImageType; // Progress listening... typedef itk::SimpleMemberCommand< PartialVolumeAnalysisHistogramCalculator > ITKCommandType; ITKCommandType::Pointer progressListener; progressListener = ITKCommandType::New(); progressListener->SetCallbackFunction( this, &PartialVolumeAnalysisHistogramCalculator::UnmaskedStatisticsProgressUpdate ); // Issue 100 artificial progress events since ScalarIMageToHistogramGenerator // does not (yet?) support progress reporting this->InvokeEvent( itk::StartEvent() ); for ( unsigned int i = 0; i < 100; ++i ) { this->UnmaskedStatisticsProgressUpdate(); } // Calculate statistics (separate filter) typedef itk::StatisticsImageFilter< ImageType > StatisticsFilterType; typename StatisticsFilterType::Pointer statisticsFilter = StatisticsFilterType::New(); statisticsFilter->SetInput( image ); unsigned long observerTag = statisticsFilter->AddObserver( itk::ProgressEvent(), progressListener ); statisticsFilter->Update(); statisticsFilter->RemoveObserver( observerTag ); this->InvokeEvent( itk::EndEvent() ); statistics.N = image->GetBufferedRegion().GetNumberOfPixels(); statistics.Min = statisticsFilter->GetMinimum(); statistics.Max = statisticsFilter->GetMaximum(); statistics.Mean = statisticsFilter->GetMean(); statistics.Median = 0.0; statistics.Sigma = statisticsFilter->GetSigma(); statistics.RMS = sqrt( statistics.Mean * statistics.Mean + statistics.Sigma * statistics.Sigma ); typename ImageType::Pointer inImage = const_cast(image); // Calculate histogram typedef itk::Statistics::ScalarImageToHistogramGenerator< ImageType > HistogramGeneratorType; typename HistogramGeneratorType::Pointer histogramGenerator = HistogramGeneratorType::New(); histogramGenerator->SetInput( inImage ); histogramGenerator->SetMarginalScale( 10 ); // Defines y-margin width of histogram histogramGenerator->SetNumberOfBins( m_NumberOfBins ); // CT range [-1024, +2048] --> bin size 4 values histogramGenerator->SetHistogramMin( statistics.Min ); histogramGenerator->SetHistogramMax( statistics.Max ); histogramGenerator->Compute(); *histogram = histogramGenerator->GetOutput(); } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalCalculateStatisticsMasked( const itk::Image< TPixel, VImageDimension > *image, itk::Image< unsigned char, VImageDimension > *maskImage, Statistics &, typename HistogramType::ConstPointer *histogram ) { MITK_DEBUG << "InternalCalculateStatisticsMasked() start"; typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::Image< unsigned char, VImageDimension > MaskImageType; // generate a list sample of angles at positions // where the fiber-prob is higher than .2*maxprob typedef TPixel MeasurementType; const unsigned int MeasurementVectorLength = 1; typedef itk::Vector< MeasurementType , MeasurementVectorLength > MeasurementVectorType; typedef itk::Statistics::ListSample< MeasurementVectorType > ListSampleType; typename ListSampleType::Pointer listSample = ListSampleType::New(); listSample->SetMeasurementVectorSize( MeasurementVectorLength ); itk::ImageRegionConstIterator itmask(maskImage, maskImage->GetLargestPossibleRegion()); itk::ImageRegionConstIterator itimage(image, image->GetLargestPossibleRegion()); itmask.GoToBegin(); itimage.GoToBegin(); while( !itmask.IsAtEnd() ) { if(itmask.Get() != 0) { // apend to list MeasurementVectorType mv; mv[0] = ( MeasurementType ) itimage.Get(); listSample->PushBack(mv); } ++itmask; ++itimage; } // generate a histogram from the list sample typedef double HistogramMeasurementType; typedef itk::Statistics::Histogram< HistogramMeasurementType, itk::Statistics::DenseFrequencyContainer2 > HistogramType; typedef itk::Statistics::SampleToHistogramFilter< ListSampleType, HistogramType > GeneratorType; typename GeneratorType::Pointer generator = GeneratorType::New(); typename GeneratorType::HistogramType::SizeType size(MeasurementVectorLength); size.Fill(m_NumberOfBins); generator->SetHistogramSize( size ); generator->SetInput( listSample ); generator->SetMarginalScale( 10.0 ); generator->Update(); *histogram = generator->GetOutput(); } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalCropAdditionalImage( itk::Image< TPixel, VImageDimension > *image, int additionalIndex ) { typedef itk::Image< TPixel, VImageDimension > ImageType; typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType; typename ROIFilterType::Pointer roi = ROIFilterType::New(); roi->SetRegionOfInterest(m_CropRegion); roi->SetInput(image); roi->Update(); m_InternalAdditionalResamplingImages[additionalIndex] = mitk::Image::New(); m_InternalAdditionalResamplingImages[additionalIndex]->InitializeByItk(roi->GetOutput()); m_InternalAdditionalResamplingImages[additionalIndex]->SetVolume(roi->GetOutput()->GetBufferPointer()); } template < typename TPixel, unsigned int VImageDimension > void PartialVolumeAnalysisHistogramCalculator::InternalCalculateMaskFromPlanarFigure( itk::Image< TPixel, VImageDimension > *image, unsigned int axis ) { MITK_DEBUG << "InternalCalculateMaskFromPlanarFigure() start"; typedef itk::Image< TPixel, VImageDimension > ImageType; // Generate mask image as new image with same header as input image and // initialize with "1". MaskImage3DType::Pointer newMaskImage = MaskImage3DType::New(); newMaskImage->SetSpacing( image->GetSpacing() ); // Set the image spacing newMaskImage->SetOrigin( image->GetOrigin() ); // Set the image origin newMaskImage->SetDirection( image->GetDirection() ); // Set the image direction newMaskImage->SetRegions( image->GetLargestPossibleRegion() ); newMaskImage->Allocate(); newMaskImage->FillBuffer( 1 ); // Generate VTK polygon from (closed) PlanarFigure polyline // (The polyline points are shifted by -0.5 in z-direction to make sure // that the extrusion filter, which afterwards elevates all points by +0.5 // in z-direction, creates a 3D object which is cut by the the plane z=0) const mitk::PlaneGeometry *planarFigureGeometry2D = m_PlanarFigure->GetPlaneGeometry(); const typename PlanarFigure::PolyLineType planarFigurePolyline = m_PlanarFigure->GetPolyLine( 0 ); const mitk::BaseGeometry *imageGeometry3D = m_InternalImage->GetGeometry( 0 ); vtkPolyData *polyline = vtkPolyData::New(); polyline->Allocate( 1, 1 ); // Determine x- and y-dimensions depending on principal axis int i0, i1; switch ( axis ) { case 0: i0 = 1; i1 = 2; break; case 1: i0 = 0; i1 = 2; break; case 2: default: i0 = 0; i1 = 1; break; } // Create VTK polydata object of polyline contour bool outOfBounds = false; vtkPoints *points = vtkPoints::New(); typename PlanarFigure::PolyLineType::const_iterator it; for ( it = planarFigurePolyline.begin(); it != planarFigurePolyline.end(); ++it ) { Point3D point3D; // Convert 2D point back to the local index coordinates of the selected // image mitk::Point2D point2D = *it; planarFigureGeometry2D->WorldToIndex(point2D, point2D); point2D[0] -= 0.5/m_UpsamplingFactor; point2D[1] -= 0.5/m_UpsamplingFactor; planarFigureGeometry2D->IndexToWorld(point2D, point2D); planarFigureGeometry2D->Map( point2D, point3D ); // Polygons (partially) outside of the image bounds can not be processed // further due to a bug in vtkPolyDataToImageStencil if ( !imageGeometry3D->IsInside( point3D ) ) { outOfBounds = true; } imageGeometry3D->WorldToIndex( point3D, point3D ); point3D[i0] += 0.5; point3D[i1] += 0.5; // Add point to polyline array points->InsertNextPoint( point3D[i0], point3D[i1], -0.5 ); } polyline->SetPoints( points ); points->Delete(); if ( outOfBounds ) { polyline->Delete(); throw std::runtime_error( "Figure at least partially outside of image bounds!" ); } std::size_t numberOfPoints = planarFigurePolyline.size(); auto ptIds = new vtkIdType[numberOfPoints]; for ( std::size_t i = 0; i < numberOfPoints; ++i ) { ptIds[i] = i; } polyline->InsertNextCell( VTK_POLY_LINE, numberOfPoints, ptIds ); // Extrude the generated contour polygon vtkLinearExtrusionFilter *extrudeFilter = vtkLinearExtrusionFilter::New(); extrudeFilter->SetInputData( polyline ); extrudeFilter->SetScaleFactor( 1 ); extrudeFilter->SetExtrusionTypeToNormalExtrusion(); extrudeFilter->SetVector( 0.0, 0.0, 1.0 ); // Make a stencil from the extruded polygon vtkPolyDataToImageStencil *polyDataToImageStencil = vtkPolyDataToImageStencil::New(); polyDataToImageStencil->SetInputConnection( extrudeFilter->GetOutputPort() ); // Export from ITK to VTK (to use a VTK filter) typedef itk::VTKImageImport< MaskImage3DType > ImageImportType; typedef itk::VTKImageExport< MaskImage3DType > ImageExportType; typename ImageExportType::Pointer itkExporter = ImageExportType::New(); itkExporter->SetInput( newMaskImage ); vtkImageImport *vtkImporter = vtkImageImport::New(); this->ConnectPipelines( itkExporter, vtkImporter ); vtkImporter->Update(); // Apply the generated image stencil to the input image vtkImageStencil *imageStencilFilter = vtkImageStencil::New(); imageStencilFilter->SetInputData( vtkImporter->GetOutput() ); imageStencilFilter->SetStencilConnection(polyDataToImageStencil->GetOutputPort() ); imageStencilFilter->ReverseStencilOff(); imageStencilFilter->SetBackgroundValue( 0 ); imageStencilFilter->Update(); // Export from VTK back to ITK vtkImageExport *vtkExporter = vtkImageExport::New(); vtkExporter->SetInputData( imageStencilFilter->GetOutput() ); vtkExporter->Update(); typename ImageImportType::Pointer itkImporter = ImageImportType::New(); this->ConnectPipelines( vtkExporter, itkImporter ); itkImporter->Update(); // calculate cropping bounding box m_InternalImageMask3D = itkImporter->GetOutput(); m_InternalImageMask3D->SetDirection(image->GetDirection()); itk::ImageRegionIterator itmask(m_InternalImageMask3D, m_InternalImageMask3D->GetLargestPossibleRegion()); itmask.GoToBegin(); while( !itmask.IsAtEnd() ) { if(itmask.Get() != 0) { typename ImageType::IndexType index = itmask.GetIndex(); for(unsigned int thick=0; thick<2*m_PlanarFigureThickness+1; thick++) { index[axis] = thick; m_InternalImageMask3D->SetPixel(index, itmask.Get()); } } ++itmask; } itmask.GoToBegin(); itk::ImageRegionIterator itimage(image, image->GetLargestPossibleRegion()); itimage.GoToBegin(); typename ImageType::SizeType lowersize; lowersize.Fill(std::numeric_limits::max()); typename ImageType::SizeType uppersize; uppersize.Fill(std::numeric_limits::min()); while( !itmask.IsAtEnd() ) { if(itmask.Get() == 0) { itimage.Set(0); } else { typename ImageType::IndexType index = itimage.GetIndex(); typename ImageType::SizeType signedindex; signedindex[0] = index[0]; signedindex[1] = index[1]; signedindex[2] = index[2]; lowersize[0] = signedindex[0] < lowersize[0] ? signedindex[0] : lowersize[0]; lowersize[1] = signedindex[1] < lowersize[1] ? signedindex[1] : lowersize[1]; lowersize[2] = signedindex[2] < lowersize[2] ? signedindex[2] : lowersize[2]; uppersize[0] = signedindex[0] > uppersize[0] ? signedindex[0] : uppersize[0]; uppersize[1] = signedindex[1] > uppersize[1] ? signedindex[1] : uppersize[1]; uppersize[2] = signedindex[2] > uppersize[2] ? signedindex[2] : uppersize[2]; } ++itmask; ++itimage; } typename ImageType::IndexType index; index[0] = lowersize[0]; index[1] = lowersize[1]; index[2] = lowersize[2]; typename ImageType::SizeType size; size[0] = uppersize[0] - lowersize[0] + 1; size[1] = uppersize[1] - lowersize[1] + 1; size[2] = uppersize[2] - lowersize[2] + 1; m_CropRegion = itk::ImageRegion<3>(index, size); // crop internal image typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > ROIFilterType; typename ROIFilterType::Pointer roi = ROIFilterType::New(); roi->SetRegionOfInterest(m_CropRegion); roi->SetInput(image); roi->Update(); m_InternalImage = mitk::Image::New(); m_InternalImage->InitializeByItk(roi->GetOutput()); m_InternalImage->SetVolume(roi->GetOutput()->GetBufferPointer()); // crop internal mask typedef itk::RegionOfInterestImageFilter< MaskImage3DType, MaskImage3DType > ROIMaskFilterType; typename ROIMaskFilterType::Pointer roi2 = ROIMaskFilterType::New(); roi2->SetRegionOfInterest(m_CropRegion); roi2->SetInput(m_InternalImageMask3D); roi2->Update(); m_InternalImageMask3D = roi2->GetOutput(); // Clean up VTK objects polyline->Delete(); extrudeFilter->Delete(); polyDataToImageStencil->Delete(); vtkImporter->Delete(); imageStencilFilter->Delete(); //vtkExporter->Delete(); // TODO: crashes when outcommented; memory leak?? delete[] ptIds; } void PartialVolumeAnalysisHistogramCalculator::UnmaskedStatisticsProgressUpdate() { // Need to throw away every second progress event to reach a final count of // 100 since two consecutive filters are used in this case static int updateCounter = 0; if ( updateCounter++ % 2 == 0 ) { this->InvokeEvent( itk::ProgressEvent() ); } } void PartialVolumeAnalysisHistogramCalculator::MaskedStatisticsProgressUpdate() { this->InvokeEvent( itk::ProgressEvent() ); } } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.cpp b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.cpp index 1ba79aa637..4ce6bd00b2 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.cpp +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.cpp @@ -1,198 +1,291 @@ /*=================================================================== 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 "mitkFiberBundleMapper2D.h" -#include +#include "mitkBaseRenderer.h" +#include "mitkDataNode.h" #include -#include +#include +#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include -#include #include +class vtkShaderCallback : public vtkCommand +{ +public: + static vtkShaderCallback *New() + { + return new vtkShaderCallback; + } + mitk::BaseRenderer *renderer; + mitk::DataNode *node; + + virtual void Execute(vtkObject *, unsigned long, void*cbo) + { + vtkOpenGLHelper *cellBO = reinterpret_cast(cbo); + + float fiberOpacity; + int fiberFading = 300; + float fiberThickness; + + node->GetOpacity(fiberOpacity, nullptr); + node->GetFloatProperty("shader.mitkShaderFiberClipping.fiberThickness", fiberThickness); + node->GetIntProperty("shader.mitkShaderFiberClipping.fiberFadingON", fiberFading); + + cellBO->Program->SetUniformf("fiberOpacity", fiberOpacity); + cellBO->Program->SetUniformi("fiberFadingON", fiberFading); + cellBO->Program->SetUniformf("fiberThickness", fiberThickness); + + if (this->renderer) + { + //get information about current position of views + mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController(); + mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry(); + + //generate according cutting planes based on the view position + float planeNormal[3]; + planeNormal[0] = planeGeo->GetNormal()[0]; + planeNormal[1] = planeGeo->GetNormal()[1]; + planeNormal[2] = planeGeo->GetNormal()[2]; + + float tmp1 = planeGeo->GetOrigin()[0] * planeNormal[0]; + float tmp2 = planeGeo->GetOrigin()[1] * planeNormal[1]; + float tmp3 = planeGeo->GetOrigin()[2] * planeNormal[2]; + float thickness = tmp1 + tmp2 + tmp3; //attention, correct normalvector + + node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.w", thickness, renderer); + node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.x", planeNormal[0], renderer); + node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.y", planeNormal[1], renderer); + node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.z", planeNormal[2], renderer); + + float* a = new float[4]; + for (int i = 0; i < 3; ++i) + a[i] = planeNormal[i]; + + a[3] = thickness; + cellBO->Program->SetUniform4f("slicingPlane", a); + + } + } + + vtkShaderCallback() { this->renderer = 0; } +}; + + + mitk::FiberBundleMapper2D::FiberBundleMapper2D() : m_LineWidth(1) { m_lut = vtkLookupTable::New(); m_lut->Build(); } mitk::FiberBundleMapper2D::~FiberBundleMapper2D() { } mitk::FiberBundle* mitk::FiberBundleMapper2D::GetInput() { return dynamic_cast< mitk::FiberBundle * > ( GetDataNode()->GetData() ); } void mitk::FiberBundleMapper2D::Update(mitk::BaseRenderer * renderer) { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, "visible"); if ( !visible ) return; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); //check if updates occured in the node or on the display FBXLocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); //set renderer independent shader properties const DataNode::Pointer node = this->GetDataNode(); float thickness = 2.0; if(!this->GetDataNode()->GetPropertyValue("Fiber2DSliceThickness",thickness)) MITK_INFO << "FIBER2D SLICE THICKNESS PROPERTY ERROR"; bool fiberfading = false; if(!this->GetDataNode()->GetPropertyValue("Fiber2DfadeEFX",fiberfading)) MITK_INFO << "FIBER2D SLICE FADE EFX PROPERTY ERROR"; float fiberOpacity; this->GetDataNode()->GetOpacity(fiberOpacity, nullptr); node->SetFloatProperty("shader.mitkShaderFiberClipping.fiberThickness",thickness); node->SetIntProperty("shader.mitkShaderFiberClipping.fiberFadingON",fiberfading); node->SetFloatProperty("shader.mitkShaderFiberClipping.fiberOpacity",fiberOpacity); mitk::FiberBundle* fiberBundle = this->GetInput(); if (fiberBundle==nullptr) return; int lineWidth = 0; node->GetIntProperty("LineWidth", lineWidth); if (m_LineWidth!=lineWidth) { m_LineWidth = lineWidth; fiberBundle->RequestUpdate2D(); } if ( localStorage->m_LastUpdateTimeGetCurrentWorldPlaneGeometryUpdateTime() || localStorage->m_LastUpdateTimeGetUpdateTime2D() ) { this->UpdateShaderParameter(renderer); this->GenerateDataForRenderer( renderer ); } } void mitk::FiberBundleMapper2D::UpdateShaderParameter(mitk::BaseRenderer * renderer) { - //get information about current position of views - mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController(); - mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry(); - - //generate according cutting planes based on the view position - float planeNormal[3]; - planeNormal[0] = planeGeo->GetNormal()[0]; - planeNormal[1] = planeGeo->GetNormal()[1]; - planeNormal[2] = planeGeo->GetNormal()[2]; - - float tmp1 = planeGeo->GetOrigin()[0] * planeNormal[0]; - float tmp2 = planeGeo->GetOrigin()[1] * planeNormal[1]; - float tmp3 = planeGeo->GetOrigin()[2] * planeNormal[2]; - float thickness = tmp1 + tmp2 + tmp3; //attention, correct normalvector - - DataNode::Pointer node = this->GetDataNode(); - node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.w",thickness,renderer); - node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.x",planeNormal[0],renderer); - node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.y",planeNormal[1],renderer); - node->SetFloatProperty("shader.mitkShaderFiberClipping.slicingPlane.z",planeNormal[2],renderer); + // see new vtkShaderCallback + } // vtkActors and Mappers are feeded here void mitk::FiberBundleMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { - mitk::FiberBundle* fiberBundle = this->GetInput(); - - //the handler of local storage gets feeded in this method with requested data for related renderwindow - FBXLocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); - - mitk::DataNode* node = this->GetDataNode(); - if ( node == nullptr ) - return; - - vtkSmartPointer fiberPolyData = fiberBundle->GetFiberPolyData(); - if (fiberPolyData == nullptr) - return; - - fiberPolyData->GetPointData()->AddArray(fiberBundle->GetFiberColors()); - localStorage->m_FiberMapper->ScalarVisibilityOn(); - localStorage->m_FiberMapper->SetScalarModeToUsePointFieldData(); - localStorage->m_FiberMapper->SetLookupTable(m_lut); //apply the properties after the slice was set - localStorage->m_PointActor->GetProperty()->SetOpacity(0.999); - localStorage->m_FiberMapper->SelectColorArray("FIBER_COLORS"); - - localStorage->m_FiberMapper->SetInputData(fiberPolyData); - localStorage->m_PointActor->SetMapper(localStorage->m_FiberMapper); - localStorage->m_PointActor->GetProperty()->ShadingOn(); - localStorage->m_PointActor->GetProperty()->SetLineWidth(m_LineWidth); - - // Applying shading properties - this->ApplyShaderProperties(renderer); - - // We have been modified => save this for next Update() - localStorage->m_LastUpdateTime.Modified(); + mitk::FiberBundle* fiberBundle = this->GetInput(); + + //the handler of local storage gets feeded in this method with requested data for related renderwindow + FBXLocalStorage *localStorage = m_LocalStorageHandler.GetLocalStorage(renderer); + + mitk::DataNode* node = this->GetDataNode(); + if (node == nullptr) + return; + + vtkSmartPointer fiberPolyData = fiberBundle->GetFiberPolyData(); + if (fiberPolyData == nullptr) + return; + + fiberPolyData->GetPointData()->AddArray(fiberBundle->GetFiberColors()); + localStorage->m_FiberMapper->ScalarVisibilityOn(); + localStorage->m_FiberMapper->SetScalarModeToUsePointFieldData(); + localStorage->m_FiberMapper->SetLookupTable(m_lut); //apply the properties after the slice was set + localStorage->m_PointActor->GetProperty()->SetOpacity(0.999); + localStorage->m_FiberMapper->SelectColorArray("FIBER_COLORS"); + + localStorage->m_FiberMapper->SetInputData(fiberPolyData); + localStorage->m_FiberMapper->SetVertexShaderCode( + "//VTK::System::Dec\n" + "attribute vec4 vertexMC;\n" + + "//VTK::Normal::Dec\n" + "uniform mat4 MCDCMatrix;\n" + + "//VTK::Color::Dec\n" + + "varying vec4 positionWorld;\n" + "varying vec4 colorVertex;\n" + + "void main(void)\n" + "{\n" + " colorVertex = scalarColor;\n" + " positionWorld = vertexMC;\n" + " gl_Position = MCDCMatrix * vertexMC;\n" + "}\n" + ); + localStorage->m_FiberMapper->SetFragmentShaderCode( + "//VTK::System::Dec\n" // always start with this line + "//VTK::Output::Dec\n" // always have this line in your FS + "uniform vec4 slicingPlane;\n" + "uniform float fiberThickness;\n" + "uniform int fiberFadingON;\n" + "uniform float fiberOpacity;\n" + + "varying vec4 positionWorld;\n" + "varying vec4 colorVertex;\n" + + "void main(void)\n" + "{\n" + " float r1 = dot(positionWorld.xyz, slicingPlane.xyz) - slicingPlane.w;\n" + + " if (abs(r1) >= fiberThickness)\n" + " discard;\n" + + " if (fiberFadingON != 0)\n" + " {\n" + " float x = (r1 + fiberThickness) / (fiberThickness*2.0);\n" + " x = 1.0 - x;\n" + " gl_FragColor = vec4(colorVertex.xyz*x, fiberOpacity);\n" + " }\n" + " else{\n" + " gl_FragColor = vec4(colorVertex.xyz,fiberOpacity);\n" + " }\n" + "}\n" + ); + + vtkSmartPointer myCallback = vtkSmartPointer::New(); + myCallback->renderer = renderer; + myCallback->node = this->GetDataNode(); + localStorage->m_FiberMapper->AddObserver(vtkCommand::UpdateShaderEvent,myCallback); + + localStorage->m_PointActor->SetMapper(localStorage->m_FiberMapper); + localStorage->m_PointActor->GetProperty()->ShadingOn(); + localStorage->m_PointActor->GetProperty()->SetLineWidth(m_LineWidth); + + // Applying shading properties + this->ApplyShaderProperties(renderer); + + // We have been modified => save this for next Update() + localStorage->m_LastUpdateTime.Modified(); } vtkProp* mitk::FiberBundleMapper2D::GetVtkProp(mitk::BaseRenderer *renderer) { this->Update(renderer); return m_LocalStorageHandler.GetLocalStorage(renderer)->m_PointActor; } void mitk::FiberBundleMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { Superclass::SetDefaultProperties(node, renderer, overwrite); - node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping")); - - // Shaders - IShaderRepository* shaderRepo = CoreServices::GetShaderRepository(); - if (shaderRepo) - { - shaderRepo->AddDefaultProperties(node, renderer, overwrite); - } +// node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping")); //add other parameters to propertylist node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(1.0f), renderer, overwrite ); node->AddProperty( "Fiber2DfadeEFX", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "color", mitk::ColorProperty::New(1.0,1.0,1.0), renderer, overwrite); } mitk::FiberBundleMapper2D::FBXLocalStorage::FBXLocalStorage() { m_PointActor = vtkSmartPointer::New(); - m_FiberMapper = vtkSmartPointer::New(); + m_FiberMapper = vtkSmartPointer::New(); } diff --git a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.h b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.h index 538174c223..984e79a0d0 100644 --- a/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.h +++ b/Modules/DiffusionImaging/DiffusionIO/mitkFiberBundleMapper2D.h @@ -1,109 +1,110 @@ /*=================================================================== 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 FiberBundleMAPPER2D_H_HEADER_INCLUDED #define FiberBundleMAPPER2D_H_HEADER_INCLUDED //MITK Rendering #include #include //#include #include #include #include +#define MITKFIBERBUNDLEMAPPER2D_POLYDATAMAPPER vtkOpenGLPolyDataMapper class vtkActor; //class vtkPropAssembly; //lets see if we need it class mitkBaseRenderer; -class vtkPolyDataMapper; +class MITKFIBERBUNDLEMAPPER2D_POLYDATAMAPPER; class vtkCutter; class vtkPlane; class vtkPolyData; namespace mitk { struct IShaderRepository; class FiberBundleMapper2D : public VtkMapper { public: mitkClassMacro(FiberBundleMapper2D, VtkMapper); itkFactorylessNewMacro(Self) itkCloneMacro(Self) mitk::FiberBundle* GetInput(); /** \brief Checks whether this mapper needs to update itself and generate data. */ virtual void Update(mitk::BaseRenderer * renderer) override; static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = nullptr, bool overwrite = false ); //### methods of MITK-VTK rendering pipeline virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) override; //### end of methods of MITK-VTK rendering pipeline class FBXLocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Point Actor of a 2D render window. */ vtkSmartPointer m_PointActor; /** \brief Point Mapper of a 2D render window. */ - vtkSmartPointer m_FiberMapper; + vtkSmartPointer m_FiberMapper; vtkSmartPointer m_SlicingPlane; //needed later when optimized 2D mapper vtkSmartPointer m_SlicedResult; //might be depricated in optimized 2D mapper /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief Constructor of the local storage. Do as much actions as possible in here to avoid double executions. */ FBXLocalStorage(); //if u copy&paste from this 2Dmapper, be aware that the implementation of this constructor is in the cpp file ~FBXLocalStorage() { } }; /** \brief This member holds all three LocalStorages for the three 2D render windows. */ mitk::LocalStorageHandler m_LocalStorageHandler; protected: FiberBundleMapper2D(); virtual ~FiberBundleMapper2D(); /** Does the actual resampling, without rendering. */ virtual void GenerateDataForRenderer(mitk::BaseRenderer*) override; void UpdateShaderParameter(mitk::BaseRenderer*); private: vtkSmartPointer m_lut; int m_LineWidth; }; }//end namespace #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h index 7a74725311..4cd008adaa 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkStreamlineTrackingFilter.h @@ -1,222 +1,220 @@ /*=================================================================== 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 __itkMLBSTrackingFilter_h_ #define __itkMLBSTrackingFilter_h_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace itk{ /** * \brief Performs streamline tracking on the input image. Depending on the tracking handler this can be a tensor, peak or machine learning based tracking. */ class MITKFIBERTRACKING_EXPORT StreamlineTrackingFilter : public ProcessObject { public: typedef StreamlineTrackingFilter Self; typedef SmartPointer Pointer; typedef SmartPointer ConstPointer; typedef ProcessObject Superclass; /** Method for creation through the object factory. */ itkFactorylessNewMacro(Self) itkCloneMacro(Self) /** Runtime information support. */ itkTypeMacro(MLBSTrackingFilter, ImageToImageFilter) typedef itk::Image ItkUcharImgType; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkFloatImgType; typedef vtkSmartPointer< vtkPolyData > PolyDataType; typedef std::deque< itk::Point > FiberType; typedef std::vector< FiberType > BundleType; volatile bool m_PauseTracking; bool m_AbortTracking; bool m_BuildFibersFinished; int m_BuildFibersReady; volatile bool m_Stop; mitk::PointSet::Pointer m_SamplingPointset; mitk::PointSet::Pointer m_StopVotePointset; mitk::PointSet::Pointer m_AlternativePointset; void SetStepSize(float v) ///< Integration step size in voxels, default is 0.5 * voxel { m_StepSizeVox = v; } void SetAngularThreshold(float v) ///< Angular threshold per step (in degree), default is 90deg x stepsize { m_AngularThresholdDeg = v; } void SetSamplingDistance(float v) ///< Maximum distance of sampling points in voxels, default is 0.25 * voxel { m_SamplingDistanceVox = v; } itkGetMacro( OutputProbabilityMap, ItkDoubleImgType::Pointer) ///< Output probability map itkGetMacro( FiberPolyData, PolyDataType ) ///< Output fibers itkGetMacro( UseOutputProbabilityMap, bool) itkSetMacro( SeedImage, ItkUcharImgType::Pointer) ///< Seeds are only placed inside of this mask. itkSetMacro( MaskImage, ItkUcharImgType::Pointer) ///< Tracking is only performed inside of this mask image. itkSetMacro( TissueImage, ItkUcharImgType::Pointer) ///< itkSetMacro( SeedsPerVoxel, int) ///< One seed placed in the center of each voxel or multiple seeds randomly placed inside each voxel. itkSetMacro( MinTractLength, float ) ///< Shorter tracts are discarded. itkSetMacro( MaxTractLength, float ) ///< Streamline progression stops if tract is longer than specified. itkSetMacro( UseStopVotes, bool ) ///< Frontal sampling points can vote for stopping the streamline even if the remaining sampling points keep pushing itkSetMacro( OnlyForwardSamples, bool ) ///< Don't use sampling points behind the current position in progression direction itkSetMacro( DeflectionMod, float ) ///< Deflection distance modifier itkSetMacro( StoppingRegions, ItkUcharImgType::Pointer) ///< Streamlines entering a stopping region will stop immediately itkSetMacro( DemoMode, bool ) itkSetMacro( SeedOnlyGm, bool ) ///< place seed points only in the gray matter itkSetMacro( ControlGmEndings, bool ) ///< itkSetMacro( NumberOfSamples, unsigned int ) ///< Number of neighborhood sampling points itkSetMacro( AposterioriCurvCheck, bool ) ///< Checks fiber curvature (angular deviation across 5mm) is larger than 30°. If yes, the streamline progression is stopped. itkSetMacro( AvoidStop, bool ) ///< Use additional sampling points to avoid premature streamline termination itkSetMacro( RandomSampling, bool ) ///< If true, the sampling points are distributed randomly around the current position, not sphericall in the specified sampling distance. itkSetMacro( NumPreviousDirections, unsigned int ) ///< How many "old" steps do we want to consider in our decision where to go next? itkSetMacro( MaxNumTracts, unsigned int ) ///< Tracking is stopped if the maximum number of tracts is exceeded itkSetMacro( Random, bool ) ///< If true, seedpoints are shuffled randomly before tracking itkSetMacro( Verbose, bool ) ///< If true, output tracking progress (might be slower) itkSetMacro( UseOutputProbabilityMap, bool) ///< If true, no tractogram but a probability map is created as output. - itkSetMacro( StopTracking, bool) ///< Set flag to stop tractography - - void SetSeedPoints(std::vector< itk::Point > seedPoints) ///< Use manually defined points in physical space as seed points instead of seed image - { - m_SeedPoints = seedPoints; - this->Modified(); + + ///< Use manually defined points in physical space as seed points instead of seed image + void SetSeedPoints( const std::vector< itk::Point >& sP) { + m_SeedPoints = sP; } void SetTrackingHandler( mitk::TrackingDataHandler* h ) ///< { m_TrackingHandler = h; } virtual void Update() override{ this->GenerateData(); } std::string GetStatusText(); protected: void GenerateData() override; StreamlineTrackingFilter(); ~StreamlineTrackingFilter() {} void InitGrayMatterEndings(); void CheckFiberForGmEnding(FiberType* fib); void FiberToProbmap(FiberType* fib); void GetSeedPointsFromSeedImage(); void CalculateNewPosition(itk::Point& pos, vnl_vector_fixed& dir); ///< Calculate next integration step. float FollowStreamline(itk::Point start_pos, vnl_vector_fixed dir, FiberType* fib, float tractLength, bool front); ///< Start streamline in one direction. bool IsValidPosition(const itk::Point& pos); ///< Are we outside of the mask image? bool IsInGm(const itk::Point &pos); vnl_vector_fixed GetNewDirection(itk::Point& pos, std::deque< vnl_vector_fixed >& olddirs, itk::Index<3>& oldIndex); ///< Determine new direction by sample voting at the current position taking the last progression direction into account. std::vector< vnl_vector_fixed > CreateDirections(int NPoints); void BeforeTracking(); void AfterTracking(); PolyDataType m_FiberPolyData; vtkSmartPointer m_Points; vtkSmartPointer m_Cells; BundleType m_Tractogram; BundleType m_GmStubs; ItkUcharImgType::Pointer m_StoppingRegions; ItkUcharImgType::Pointer m_SeedImage; ItkUcharImgType::Pointer m_MaskImage; ItkUcharImgType::Pointer m_TissueImage; ItkDoubleImgType::Pointer m_OutputProbabilityMap; float m_AngularThresholdDeg; float m_StepSizeVox; float m_SamplingDistanceVox; float m_AngularThreshold; float m_StepSize; int m_MaxLength; float m_MinTractLength; float m_MaxTractLength; int m_SeedsPerVoxel; bool m_AvoidStop; bool m_RandomSampling; float m_SamplingDistance; float m_DeflectionMod; bool m_OnlyForwardSamples; bool m_UseStopVotes; unsigned int m_NumberOfSamples; unsigned int m_NumPreviousDirections; int m_WmLabel; int m_GmLabel; bool m_SeedOnlyGm; bool m_ControlGmEndings; int m_MaxNumTracts; bool m_Verbose; bool m_AposterioriCurvCheck; bool m_DemoMode; bool m_Random; bool m_UseOutputProbabilityMap; std::vector< itk::Point > m_SeedPoints; unsigned int m_CurrentTracts; unsigned int m_Progress; bool m_StopTracking; void BuildFibers(bool check); int CheckCurvature(FiberType* fib, bool front); // decision forest mitk::TrackingDataHandler* m_TrackingHandler; std::vector< PolyDataType > m_PolyDataContainer; std::chrono::time_point m_StartTime; std::chrono::time_point m_EndTime; private: }; } //#ifndef ITK_MANUAL_INSTANTIATION //#include "itkMLBSTrackingFilter.cpp" //#endif #endif //__itkMLBSTrackingFilter_h_ diff --git a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp index 9418e0878b..31d4ec4c46 100755 --- a/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp +++ b/Modules/DiffusionImaging/FiberTracking/IODataStructures/FiberBundle/mitkFiberBundle.cpp @@ -1,2328 +1,2325 @@ /*=================================================================== 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 _USE_MATH_DEFINES #include "mitkFiberBundle.h" #include #include #include #include "mitkImagePixelReadAccessor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const char* mitk::FiberBundle::FIBER_ID_ARRAY = "Fiber_IDs"; using namespace std; mitk::FiberBundle::FiberBundle( vtkPolyData* fiberPolyData ) : m_NumFibers(0) { m_FiberWeights = vtkSmartPointer::New(); m_FiberWeights->SetName("FIBER_WEIGHTS"); m_FiberPolyData = vtkSmartPointer::New(); if (fiberPolyData != nullptr) m_FiberPolyData = fiberPolyData; this->UpdateFiberGeometry(); this->GenerateFiberIds(); this->ColorFibersByOrientation(); } mitk::FiberBundle::~FiberBundle() { } mitk::FiberBundle::Pointer mitk::FiberBundle::GetDeepCopy() { mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(m_FiberPolyData); newFib->SetFiberColors(this->m_FiberColors); newFib->SetFiberWeights(this->m_FiberWeights); return newFib; } vtkSmartPointer mitk::FiberBundle::GeneratePolyDataByIds(std::vector fiberIds) { vtkSmartPointer newFiberPolyData = vtkSmartPointer::New(); vtkSmartPointer newLineSet = vtkSmartPointer::New(); vtkSmartPointer newPointSet = vtkSmartPointer::New(); auto finIt = fiberIds.begin(); while ( finIt != fiberIds.end() ) { if (*finIt < 0 || *finIt>GetNumFibers()){ MITK_INFO << "FiberID can not be negative or >NumFibers!!! check id Extraction!" << *finIt; break; } vtkSmartPointer fiber = m_FiberIdDataSet->GetCell(*finIt);//->DeepCopy(fiber); vtkSmartPointer fibPoints = fiber->GetPoints(); vtkSmartPointer newFiber = vtkSmartPointer::New(); newFiber->GetPointIds()->SetNumberOfIds( fibPoints->GetNumberOfPoints() ); for(int i=0; iGetNumberOfPoints(); i++) { newFiber->GetPointIds()->SetId(i, newPointSet->GetNumberOfPoints()); newPointSet->InsertNextPoint(fibPoints->GetPoint(i)[0], fibPoints->GetPoint(i)[1], fibPoints->GetPoint(i)[2]); } newLineSet->InsertNextCell(newFiber); ++finIt; } newFiberPolyData->SetPoints(newPointSet); newFiberPolyData->SetLines(newLineSet); return newFiberPolyData; } // merge two fiber bundles mitk::FiberBundle::Pointer mitk::FiberBundle::AddBundle(mitk::FiberBundle* fib) { if (fib==nullptr) { MITK_WARN << "trying to call AddBundle with nullptr argument"; return nullptr; } MITK_INFO << "Adding fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); // add current fiber bundle vtkSmartPointer weights = vtkSmartPointer::New(); weights->SetNumberOfValues(this->GetNumFibers()+fib->GetNumFibers()); unsigned int counter = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } weights->InsertValue(counter, this->GetFiberWeight(i)); vNewLines->InsertNextCell(container); counter++; } // add new fiber bundle for (int i=0; iGetFiberPolyData()->GetNumberOfCells(); i++) { vtkCell* cell = fib->GetFiberPolyData()->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p); vtkIdType id = vNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } weights->InsertValue(counter, fib->GetFiberWeight(i)); vNewLines->InsertNextCell(container); counter++; } // initialize PolyData vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(vNewPolyData); newFib->SetFiberWeights(weights); return newFib; } // subtract two fiber bundles mitk::FiberBundle::Pointer mitk::FiberBundle::SubtractBundle(mitk::FiberBundle* fib) { MITK_INFO << "Subtracting fibers"; vtkSmartPointer vNewPolyData = vtkSmartPointer::New(); vtkSmartPointer vNewLines = vtkSmartPointer::New(); vtkSmartPointer vNewPoints = vtkSmartPointer::New(); std::vector< std::vector< itk::Point > > points1; for( int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (points==nullptr || numPoints<=0) continue; itk::Point start = GetItkPoint(points->GetPoint(0)); itk::Point end = GetItkPoint(points->GetPoint(numPoints-1)); points1.push_back( {start, end} ); } std::vector< std::vector< itk::Point > > points2; for( int i=0; iGetNumFibers(); i++ ) { vtkCell* cell = fib->GetFiberPolyData()->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (points==nullptr || numPoints<=0) continue; itk::Point start = GetItkPoint(points->GetPoint(0)); itk::Point end = GetItkPoint(points->GetPoint(numPoints-1)); points2.push_back( {start, end} ); } int progress = 0; std::vector< int > ids; #pragma omp parallel for for (int i=0; i<(int)points1.size(); i++) { #pragma omp critical { progress++; std::cout << (int)(100*(float)progress/points1.size()) << "%" << '\r'; cout.flush(); } bool match = false; for (unsigned int j=0; jGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (points==nullptr || numPoints<=0) continue; vtkSmartPointer container = vtkSmartPointer::New(); for( int j=0; jInsertNextPoint(points->GetPoint(j)); container->GetPointIds()->InsertNextId(id); } vNewLines->InsertNextCell(container); } if(vNewLines->GetNumberOfCells()==0) return nullptr; // initialize PolyData vNewPolyData->SetPoints(vNewPoints); vNewPolyData->SetLines(vNewLines); // initialize fiber bundle return mitk::FiberBundle::New(vNewPolyData); } itk::Point mitk::FiberBundle::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } /* * set PolyData (additional flag to recompute fiber geometry, default = true) */ void mitk::FiberBundle::SetFiberPolyData(vtkSmartPointer fiberPD, bool updateGeometry) { if (fiberPD == nullptr) this->m_FiberPolyData = vtkSmartPointer::New(); else m_FiberPolyData->DeepCopy(fiberPD); m_NumFibers = m_FiberPolyData->GetNumberOfLines(); if (updateGeometry) UpdateFiberGeometry(); GenerateFiberIds(); ColorFibersByOrientation(); } /* * return vtkPolyData */ vtkSmartPointer mitk::FiberBundle::GetFiberPolyData() const { return m_FiberPolyData; } void mitk::FiberBundle::ColorFibersByOrientation() { //===== FOR WRITING A TEST ======================== // colorT size == tupelComponents * tupelElements // compare color results // to cover this code 100% also PolyData needed, where colorarray already exists // + one fiber with exactly 1 point // + one fiber with 0 points //================================================= vtkPoints* extrPoints = nullptr; extrPoints = m_FiberPolyData->GetPoints(); int numOfPoints = 0; if (extrPoints!=nullptr) numOfPoints = extrPoints->GetNumberOfPoints(); //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; int componentSize = 4; m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(numOfPoints * componentSize); m_FiberColors->SetNumberOfComponents(componentSize); m_FiberColors->SetName("FIBER_COLORS"); int numOfFibers = m_FiberPolyData->GetNumberOfLines(); if (numOfFibers < 1) return; /* extract single fibers of fiberBundle */ vtkCellArray* fiberList = m_FiberPolyData->GetLines(); fiberList->InitTraversal(); for (int fi=0; fiGetNextCell(pointsPerFiber, idList); /* single fiber checkpoints: is number of points valid */ if (pointsPerFiber > 1) { /* operate on points of single fiber */ for (int i=0; i 0) { /* The color value of the current point is influenced by the previous point and next point. */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; vnl_vector_fixed< double, 3 > diff; diff = (diff1 - diff2) / 2.0; diff.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff[2])); rgba[3] = (unsigned char) (255.0); } else if (i==0) { /* First point has no previous point, therefore only diff1 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > nextPntvtk(extrPoints->GetPoint(idList[i+1])[0], extrPoints->GetPoint(idList[i+1])[1], extrPoints->GetPoint(idList[i+1])[2]); vnl_vector_fixed< double, 3 > diff1; diff1 = currentPntvtk - nextPntvtk; diff1.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff1[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff1[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff1[2])); rgba[3] = (unsigned char) (255.0); } else if (i==pointsPerFiber-1) { /* Last point has no next point, therefore only diff2 is taken */ vnl_vector_fixed< double, 3 > currentPntvtk(extrPoints->GetPoint(idList[i])[0], extrPoints->GetPoint(idList[i])[1],extrPoints->GetPoint(idList[i])[2]); vnl_vector_fixed< double, 3 > prevPntvtk(extrPoints->GetPoint(idList[i-1])[0], extrPoints->GetPoint(idList[i-1])[1], extrPoints->GetPoint(idList[i-1])[2]); vnl_vector_fixed< double, 3 > diff2; diff2 = currentPntvtk - prevPntvtk; diff2.normalize(); rgba[0] = (unsigned char) (255.0 * std::fabs(diff2[0])); rgba[1] = (unsigned char) (255.0 * std::fabs(diff2[1])); rgba[2] = (unsigned char) (255.0 * std::fabs(diff2[2])); rgba[3] = (unsigned char) (255.0); } - m_FiberColors->InsertTupleValue(idList[i], rgba); + m_FiberColors->InsertTypedTuple(idList[i], rgba); } } else if (pointsPerFiber == 1) { /* a single point does not define a fiber (use vertex mechanisms instead */ continue; } else { MITK_DEBUG << "Fiber with 0 points detected... please check your tractography algorithm!" ; continue; } } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::ColorFibersByCurvature(bool opacity, bool normalize) { double window = 5; //colors and alpha value for each single point, RGBA = 4 components unsigned char rgba[4] = {0,0,0,0}; int componentSize = 4; m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * componentSize); m_FiberColors->SetNumberOfComponents(componentSize); m_FiberColors->SetName("FIBER_COLORS"); mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(0.0, 0.8); lookupTable->Build(); mitkLookup->SetVtkLookupTable(lookupTable); mitkLookup->SetType(mitk::LookupTable::JET); vector< double > values; double min = 1; double max = 0; MITK_INFO << "Coloring fibers by curvature"; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures for (int j=0; j > vectors; vnl_vector_fixed< float, 3 > meanV; meanV.fill(0.0); while(dist1) { double p1[3]; points->GetPoint(c-1, p1); double p2[3]; points->GetPoint(c, p2); vnl_vector_fixed< float, 3 > v; v[0] = p2[0]-p1[0]; v[1] = p2[1]-p1[1]; v[2] = p2[2]-p1[2]; dist += v.magnitude(); v.normalize(); vectors.push_back(v); if (c==j) meanV += v; c--; } c = j; dist = 0; while(distGetPoint(c, p1); double p2[3]; points->GetPoint(c+1, p2); vnl_vector_fixed< float, 3 > v; v[0] = p2[0]-p1[0]; v[1] = p2[1]-p1[1]; v[2] = p2[2]-p1[2]; dist += v.magnitude(); v.normalize(); vectors.push_back(v); if (c==j) meanV += v; c++; } meanV.normalize(); double dev = 0; for (unsigned int c=0; c1.0) angle = 1.0; if (angle<-1.0) angle = -1.0; dev += acos(angle)*180/M_PI; } if (vectors.size()>0) dev /= vectors.size(); dev = 1.0-dev/180.0; values.push_back(dev); if (devmax) max = dev; } } unsigned int count = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); for (int j=0; j1) dev = 1; lookupTable->GetColor(dev, color); rgba[0] = (unsigned char) (255.0 * color[0]); rgba[1] = (unsigned char) (255.0 * color[1]); rgba[2] = (unsigned char) (255.0 * color[2]); - if (opacity) - rgba[3] = (unsigned char) (255.0 * dev); - else - rgba[3] = (unsigned char) (255.0); - m_FiberColors->InsertTupleValue(cell->GetPointId(j), rgba); + rgba[3] = (unsigned char) (255.0); + m_FiberColors->InsertTypedTuple(cell->GetPointId(j), rgba); count++; } } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::SetFiberOpacity(vtkDoubleArray* FAValArray) { for(long i=0; iGetNumberOfTuples(); i++) { double faValue = FAValArray->GetValue(i); faValue = faValue * 255.0; m_FiberColors->SetComponent(i,3, (unsigned char) faValue ); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::ResetFiberOpacity() { for(long i=0; iGetNumberOfTuples(); i++) m_FiberColors->SetComponent(i,3, 255.0 ); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::ColorFibersByScalarMap(mitk::Image::Pointer FAimage, bool opacity, bool normalize) { mitkPixelTypeMultiplex3( ColorFibersByScalarMap, FAimage->GetPixelType(), FAimage, opacity, normalize ); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } template void mitk::FiberBundle::ColorFibersByScalarMap(const mitk::PixelType, mitk::Image::Pointer image, bool opacity, bool normalize) { m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); m_FiberColors->SetNumberOfComponents(4); m_FiberColors->SetName("FIBER_COLORS"); mitk::ImagePixelReadAccessor readimage(image, image->GetVolumeData(0)); unsigned char rgba[4] = {0,0,0,0}; vtkPoints* pointSet = m_FiberPolyData->GetPoints(); mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(0.0, 0.8); lookupTable->Build(); mitkLookup->SetVtkLookupTable(lookupTable); mitkLookup->SetType(mitk::LookupTable::JET); double min = 9999999; double max = -9999999; for(long i=0; iGetNumberOfPoints(); ++i) { Point3D px; px[0] = pointSet->GetPoint(i)[0]; px[1] = pointSet->GetPoint(i)[1]; px[2] = pointSet->GetPoint(i)[2]; double pixelValue = readimage.GetPixelByWorldCoordinates(px); if (pixelValue>max) max = pixelValue; if (pixelValueGetNumberOfPoints(); ++i) { Point3D px; px[0] = pointSet->GetPoint(i)[0]; px[1] = pointSet->GetPoint(i)[1]; px[2] = pointSet->GetPoint(i)[2]; double pixelValue = readimage.GetPixelByWorldCoordinates(px); if (normalize) pixelValue = (pixelValue-min)/(max-min); else if (pixelValue>1) pixelValue = 1; double color[3]; lookupTable->GetColor(1-pixelValue, color); rgba[0] = (unsigned char) (255.0 * color[0]); rgba[1] = (unsigned char) (255.0 * color[1]); rgba[2] = (unsigned char) (255.0 * color[2]); if (opacity) rgba[3] = (unsigned char) (255.0 * pixelValue); else rgba[3] = (unsigned char) (255.0); - m_FiberColors->InsertTupleValue(i, rgba); + m_FiberColors->InsertTypedTuple(i, rgba); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::ColorFibersByFiberWeights(bool opacity, bool normalize) { m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); m_FiberColors->SetNumberOfComponents(4); m_FiberColors->SetName("FIBER_COLORS"); mitk::LookupTable::Pointer mitkLookup = mitk::LookupTable::New(); vtkSmartPointer lookupTable = vtkSmartPointer::New(); lookupTable->SetTableRange(0.0, 0.8); lookupTable->Build(); mitkLookup->SetVtkLookupTable(lookupTable); mitkLookup->SetType(mitk::LookupTable::JET); unsigned char rgba[4] = {0,0,0,0}; unsigned int counter = 0; float max = -999999; float min = 999999; for (int i=0; iGetFiberWeight(i); if (weight>max) max = weight; if (weightGetCell(i); int numPoints = cell->GetNumberOfPoints(); double weight = this->GetFiberWeight(i); for (int j=0; j1) v = 1; double color[3]; lookupTable->GetColor(1-v, color); rgba[0] = (unsigned char) (255.0 * color[0]); rgba[1] = (unsigned char) (255.0 * color[1]); rgba[2] = (unsigned char) (255.0 * color[2]); if (opacity) rgba[3] = (unsigned char) (255.0 * v); else rgba[3] = (unsigned char) (255.0); - m_FiberColors->InsertTupleValue(counter, rgba); + m_FiberColors->InsertTypedTuple(counter, rgba); counter++; } } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::SetFiberColors(float r, float g, float b, float alpha) { m_FiberColors = vtkSmartPointer::New(); m_FiberColors->Allocate(m_FiberPolyData->GetNumberOfPoints() * 4); m_FiberColors->SetNumberOfComponents(4); m_FiberColors->SetName("FIBER_COLORS"); unsigned char rgba[4] = {0,0,0,0}; for(long i=0; iGetNumberOfPoints(); ++i) { rgba[0] = (unsigned char) r; rgba[1] = (unsigned char) g; rgba[2] = (unsigned char) b; rgba[3] = (unsigned char) alpha; - m_FiberColors->InsertTupleValue(i, rgba); + m_FiberColors->InsertTypedTuple(i, rgba); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } void mitk::FiberBundle::GenerateFiberIds() { if (m_FiberPolyData == nullptr) return; vtkSmartPointer idFiberFilter = vtkSmartPointer::New(); idFiberFilter->SetInputData(m_FiberPolyData); idFiberFilter->CellIdsOn(); // idFiberFilter->PointIdsOn(); // point id's are not needed idFiberFilter->SetIdsArrayName(FIBER_ID_ARRAY); idFiberFilter->FieldDataOn(); idFiberFilter->Update(); m_FiberIdDataSet = idFiberFilter->GetOutput(); } mitk::FiberBundle::Pointer mitk::FiberBundle::ExtractFiberSubset(ItkUcharImgType* mask, bool anyPoint, bool invert, bool bothEnds, float fraction) { vtkSmartPointer PolyData = m_FiberPolyData; if (anyPoint) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; mitk::FiberBundle::Pointer fibCopy = this->GetDeepCopy(); fibCopy->ResampleLinear(minSpacing/5); PolyData = fibCopy->GetFiberPolyData(); } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Extracting fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cellOriginal = m_FiberPolyData->GetCell(i); int numPointsOriginal = cellOriginal->GetNumberOfPoints(); vtkPoints* pointsOriginal = cellOriginal->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1 && numPointsOriginal) { if (anyPoint) { int inside = 0; int outside = 0; if (!invert) { for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetLargestPossibleRegion().IsInside(idx) && mask->GetPixel(idx) != 0 ) { inside++; if (fraction==0) break; } else outside++; } float current_fraction = 0.0; if (inside+outside>0) current_fraction = (float)inside/(inside+outside); if (current_fraction>fraction) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } else { bool includeFiber = true; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx) != 0 && mask->GetLargestPossibleRegion().IsInside(idx) ) { inside++; includeFiber = false; break; } else outside++; } if (includeFiber) { for (int k=0; kGetPoint(k); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } else { double* start = pointsOriginal->GetPoint(0); itk::Point itkStart; itkStart[0] = start[0]; itkStart[1] = start[1]; itkStart[2] = start[2]; itk::Index<3> idxStart; mask->TransformPhysicalPointToIndex(itkStart, idxStart); double* end = pointsOriginal->GetPoint(numPointsOriginal-1); itk::Point itkEnd; itkEnd[0] = end[0]; itkEnd[1] = end[1]; itkEnd[2] = end[2]; itk::Index<3> idxEnd; mask->TransformPhysicalPointToIndex(itkEnd, idxEnd); if (invert) { if (bothEnds) { if ( mask->GetPixel(idxStart) == 0 && mask->GetPixel(idxEnd) == 0 ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } else if ( mask->GetPixel(idxStart) == 0 || mask->GetPixel(idxEnd) == 0 ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } else { if (bothEnds) { if ( mask->GetPixel(idxStart) != 0 && mask->GetPixel(idxEnd) != 0 && mask->GetLargestPossibleRegion().IsInside(idxStart) && mask->GetLargestPossibleRegion().IsInside(idxEnd) ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } else if ( (mask->GetPixel(idxStart) != 0 && mask->GetLargestPossibleRegion().IsInside(idxStart)) || (mask->GetPixel(idxEnd) != 0 && mask->GetLargestPossibleRegion().IsInside(idxEnd)) ) { for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } } } } } vtkNewCells->InsertNextCell(container); } if (vtkNewCells->GetNumberOfCells()<=0) return nullptr; vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); return mitk::FiberBundle::New(newPolyData); } mitk::FiberBundle::Pointer mitk::FiberBundle::RemoveFibersOutside(ItkUcharImgType* mask, bool invert) { float minSpacing = 1; if(mask->GetSpacing()[0]GetSpacing()[1] && mask->GetSpacing()[0]GetSpacing()[2]) minSpacing = mask->GetSpacing()[0]; else if (mask->GetSpacing()[1] < mask->GetSpacing()[2]) minSpacing = mask->GetSpacing()[1]; else minSpacing = mask->GetSpacing()[2]; mitk::FiberBundle::Pointer fibCopy = this->GetDeepCopy(); fibCopy->ResampleLinear(minSpacing/10); vtkSmartPointer PolyData =fibCopy->GetFiberPolyData(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Cutting fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); if (numPoints>1) { int newNumPoints = 0; for (int j=0; jGetPoint(j); itk::Point itkP; itkP[0] = p[0]; itkP[1] = p[1]; itkP[2] = p[2]; itk::Index<3> idx; mask->TransformPhysicalPointToIndex(itkP, idx); if ( mask->GetPixel(idx) != 0 && mask->GetLargestPossibleRegion().IsInside(idx) && !invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if ( (mask->GetPixel(idx) == 0 || !mask->GetLargestPossibleRegion().IsInside(idx)) && invert ) { vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); newNumPoints++; } else if (newNumPoints>0) { vtkNewCells->InsertNextCell(container); newNumPoints = 0; container = vtkSmartPointer::New(); } } if (newNumPoints>0) vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return nullptr; vtkSmartPointer newPolyData = vtkSmartPointer::New(); newPolyData->SetPoints(vtkNewPoints); newPolyData->SetLines(vtkNewCells); mitk::FiberBundle::Pointer newFib = mitk::FiberBundle::New(newPolyData); newFib->Compress(0.1); return newFib; } mitk::FiberBundle::Pointer mitk::FiberBundle::ExtractFiberSubset(DataNode* roi, DataStorage* storage) { if (roi==nullptr || !(dynamic_cast(roi->GetData()) || dynamic_cast(roi->GetData())) ) return nullptr; std::vector tmp = ExtractFiberIdSubset(roi, storage); if (tmp.size()<=0) return mitk::FiberBundle::New(); vtkSmartPointer pTmp = GeneratePolyDataByIds(tmp); return mitk::FiberBundle::New(pTmp); } std::vector mitk::FiberBundle::ExtractFiberIdSubset(DataNode *roi, DataStorage* storage) { std::vector result; if (roi==nullptr || roi->GetData()==nullptr) return result; mitk::PlanarFigureComposite::Pointer pfc = dynamic_cast(roi->GetData()); if (!pfc.IsNull()) // handle composite { DataStorage::SetOfObjects::ConstPointer children = storage->GetDerivations(roi); if (children->size()==0) return result; switch (pfc->getOperationType()) { case 0: // AND { MITK_INFO << "AND"; result = this->ExtractFiberIdSubset(children->ElementAt(0), storage); std::vector::iterator it; for (unsigned int i=1; iSize(); ++i) { std::vector inRoi = this->ExtractFiberIdSubset(children->ElementAt(i), storage); std::vector rest(std::min(result.size(),inRoi.size())); it = std::set_intersection(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); rest.resize( it - rest.begin() ); result = rest; } break; } case 1: // OR { MITK_INFO << "OR"; result = ExtractFiberIdSubset(children->ElementAt(0), storage); std::vector::iterator it; for (unsigned int i=1; iSize(); ++i) { it = result.end(); std::vector inRoi = ExtractFiberIdSubset(children->ElementAt(i), storage); result.insert(it, inRoi.begin(), inRoi.end()); } // remove duplicates sort(result.begin(), result.end()); it = unique(result.begin(), result.end()); result.resize( it - result.begin() ); break; } case 2: // NOT { MITK_INFO << "NOT"; for(long i=0; iGetNumFibers(); i++) result.push_back(i); std::vector::iterator it; for (unsigned int i=0; iSize(); ++i) { std::vector inRoi = ExtractFiberIdSubset(children->ElementAt(i), storage); std::vector rest(result.size()-inRoi.size()); it = std::set_difference(result.begin(), result.end(), inRoi.begin(), inRoi.end(), rest.begin() ); rest.resize( it - rest.begin() ); result = rest; } break; } } } else if ( dynamic_cast(roi->GetData()) ) // actual extraction { if ( dynamic_cast(roi->GetData()) ) { mitk::PlanarFigure::Pointer planarPoly = dynamic_cast(roi->GetData()); //create vtkPolygon using controlpoints from planarFigure polygon vtkSmartPointer polygonVtk = vtkSmartPointer::New(); for (unsigned int i=0; iGetNumberOfControlPoints(); ++i) { itk::Point p = planarPoly->GetWorldControlPoint(i); vtkIdType id = polygonVtk->GetPoints()->InsertNextPoint(p[0], p[1], p[2] ); polygonVtk->GetPointIds()->InsertNextId(id); } MITK_INFO << "Extracting with polygon"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, p1); double p2[3] = {0,0,0}; points->GetPoint(j+1, p2); double tolerance = 0.001; // Outputs double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2)) double x[3] = {0,0,0}; // The coordinate of the intersection double pcoords[3] = {0,0,0}; int subId = 0; int iD = polygonVtk->IntersectWithLine(p1, p2, tolerance, t, x, pcoords, subId); if (iD!=0) { result.push_back(i); break; } } } } else if ( dynamic_cast(roi->GetData()) ) { mitk::PlanarFigure::Pointer planarFigure = dynamic_cast(roi->GetData()); Vector3D planeNormal = planarFigure->GetPlaneGeometry()->GetNormal(); planeNormal.Normalize(); //calculate circle radius mitk::Point3D V1w = planarFigure->GetWorldControlPoint(0); //centerPoint mitk::Point3D V2w = planarFigure->GetWorldControlPoint(1); //radiusPoint double radius = V1w.EuclideanDistanceTo(V2w); radius *= radius; MITK_INFO << "Extracting with circle"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, p1); double p2[3] = {0,0,0}; points->GetPoint(j+1, p2); // Outputs double t = 0; // Parametric coordinate of intersection (0 (corresponding to p1) to 1 (corresponding to p2)) double x[3] = {0,0,0}; // The coordinate of the intersection int iD = vtkPlane::IntersectWithLine(p1,p2,planeNormal.GetDataPointer(),V1w.GetDataPointer(),t,x); if (iD!=0) { double dist = (x[0]-V1w[0])*(x[0]-V1w[0])+(x[1]-V1w[1])*(x[1]-V1w[1])+(x[2]-V1w[2])*(x[2]-V1w[2]); if( dist <= radius) { result.push_back(i); break; } } } } } return result; } return result; } void mitk::FiberBundle::UpdateFiberGeometry() { vtkSmartPointer cleaner = vtkSmartPointer::New(); cleaner->SetInputData(m_FiberPolyData); cleaner->PointMergingOff(); cleaner->Update(); m_FiberPolyData = cleaner->GetOutput(); m_FiberLengths.clear(); m_MeanFiberLength = 0; m_MedianFiberLength = 0; m_LengthStDev = 0; m_NumFibers = m_FiberPolyData->GetNumberOfCells(); if (m_FiberColors==nullptr || m_FiberColors->GetNumberOfTuples()!=m_FiberPolyData->GetNumberOfPoints()) this->ColorFibersByOrientation(); if (m_FiberWeights->GetSize()!=m_NumFibers) { m_FiberWeights = vtkSmartPointer::New(); m_FiberWeights->SetName("FIBER_WEIGHTS"); m_FiberWeights->SetNumberOfValues(m_NumFibers); this->SetFiberWeights(1); } if (m_NumFibers<=0) // no fibers present; apply default geometry { m_MinFiberLength = 0; m_MaxFiberLength = 0; mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetImageGeometry(false); float b[] = {0, 1, 0, 1, 0, 1}; geometry->SetFloatBounds(b); SetGeometry(geometry); return; } double b[6]; m_FiberPolyData->GetBounds(b); // calculate statistics for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); int p = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); float length = 0; for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); float dist = std::sqrt((p1[0]-p2[0])*(p1[0]-p2[0])+(p1[1]-p2[1])*(p1[1]-p2[1])+(p1[2]-p2[2])*(p1[2]-p2[2])); length += dist; } m_FiberLengths.push_back(length); m_MeanFiberLength += length; if (i==0) { m_MinFiberLength = length; m_MaxFiberLength = length; } else { if (lengthm_MaxFiberLength) m_MaxFiberLength = length; } } m_MeanFiberLength /= m_NumFibers; std::vector< float > sortedLengths = m_FiberLengths; std::sort(sortedLengths.begin(), sortedLengths.end()); for (int i=0; i1) m_LengthStDev /= (m_NumFibers-1); else m_LengthStDev = 0; m_LengthStDev = std::sqrt(m_LengthStDev); m_MedianFiberLength = sortedLengths.at(m_NumFibers/2); mitk::Geometry3D::Pointer geometry = mitk::Geometry3D::New(); geometry->SetFloatBounds(b); this->SetGeometry(geometry); m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } float mitk::FiberBundle::GetFiberWeight(unsigned int fiber) const { return m_FiberWeights->GetValue(fiber); } void mitk::FiberBundle::SetFiberWeights(float newWeight) { for (int i=0; iGetSize(); i++) m_FiberWeights->SetValue(i, newWeight); } void mitk::FiberBundle::SetFiberWeights(vtkSmartPointer weights) { if (m_NumFibers!=weights->GetSize()) { MITK_INFO << "Weights array not equal to number of fibers!"; return; } for (int i=0; iGetSize(); i++) m_FiberWeights->SetValue(i, weights->GetValue(i)); m_FiberWeights->SetName("FIBER_WEIGHTS"); } void mitk::FiberBundle::SetFiberWeight(unsigned int fiber, float weight) { m_FiberWeights->SetValue(fiber, weight); } void mitk::FiberBundle::SetFiberColors(vtkSmartPointer fiberColors) { for(long i=0; iGetNumberOfPoints(); ++i) { unsigned char source[4] = {0,0,0,0}; - fiberColors->GetTupleValue(i, source); + fiberColors->GetTypedTuple(i, source); unsigned char target[4] = {0,0,0,0}; target[0] = source[0]; target[1] = source[1]; target[2] = source[2]; target[3] = source[3]; - m_FiberColors->InsertTupleValue(i, target); + m_FiberColors->InsertTypedTuple(i, target); } m_UpdateTime3D.Modified(); m_UpdateTime2D.Modified(); } itk::Matrix< double, 3, 3 > mitk::FiberBundle::TransformMatrix(itk::Matrix< double, 3, 3 > m, double rx, double ry, double rz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; itk::Matrix< double, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; itk::Matrix< double, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; itk::Matrix< double, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< double, 3, 3 > rot = rotZ*rotY*rotX; m = rot*m; return m; } itk::Point mitk::FiberBundle::TransformPoint(vnl_vector_fixed< double, 3 > point, double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); point[0] -= center[0]; point[1] -= center[1]; point[2] -= center[2]; point = rot*point; point[0] += center[0]+tx; point[1] += center[1]+ty; point[2] += center[2]+tz; itk::Point out; out[0] = point[0]; out[1] = point[1]; out[2] = point[2]; return out; } void mitk::FiberBundle::TransformFibers(double rx, double ry, double rz, double tx, double ty, double tz) { rx = rx*M_PI/180; ry = ry*M_PI/180; rz = rz*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(rx); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(rx); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(ry); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(ry); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(rz); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(rz); rotZ[1][0] = -rotZ[0][1]; vnl_matrix_fixed< double, 3, 3 > rot = rotZ*rotY*rotX; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rot*dir; dir[0] += center[0]+tx; dir[1] += center[1]+ty; dir[2] += center[2]+tz; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::RotateAroundAxis(double x, double y, double z) { x = x*M_PI/180; y = y*M_PI/180; z = z*M_PI/180; vnl_matrix_fixed< double, 3, 3 > rotX; rotX.set_identity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; vnl_matrix_fixed< double, 3, 3 > rotY; rotY.set_identity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; vnl_matrix_fixed< double, 3, 3 > rotZ; rotZ.set_identity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; mitk::BaseGeometry::Pointer geom = this->GetGeometry(); mitk::Point3D center = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vnl_vector_fixed< double, 3 > dir; dir[0] = p[0]-center[0]; dir[1] = p[1]-center[1]; dir[2] = p[2]-center[2]; dir = rotZ*rotY*rotX*dir; dir[0] += center[0]; dir[1] += center[1]; dir[2] += center[2]; vtkIdType id = vtkNewPoints->InsertNextPoint(dir.data_block()); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::ScaleFibers(double x, double y, double z, bool subtractCenter) { MITK_INFO << "Scaling fibers"; boost::progress_display disp(m_NumFibers); mitk::BaseGeometry* geom = this->GetGeometry(); mitk::Point3D c = geom->GetCenter(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); if (subtractCenter) { p[0] -= c[0]; p[1] -= c[1]; p[2] -= c[2]; } p[0] *= x; p[1] *= y; p[2] *= z; if (subtractCenter) { p[0] += c[0]; p[1] += c[1]; p[2] += c[2]; } vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::TranslateFibers(double x, double y, double z) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[0] += x; p[1] += y; p[2] += z; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::MirrorFibers(unsigned int axis) { if (axis>2) return; MITK_INFO << "Mirroring fibers"; boost::progress_display disp(m_NumFibers); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); p[axis] = -p[axis]; vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::RemoveDir(vnl_vector_fixed dir, double threshold) { dir.normalize(); vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); bool discard = false; for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); vnl_vector_fixed< double, 3 > v1; v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; if (v1.magnitude()>0.001) { v1.normalize(); if (fabs(dot_product(v1,dir))>threshold) { discard = true; break; } } } if (!discard) { for (int j=0; jGetPoint(j, p1); vtkIdType id = vtkNewPoints->InsertNextPoint(p1); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } } m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); // UpdateColorCoding(); // UpdateFiberGeometry(); } bool mitk::FiberBundle::ApplyCurvatureThreshold(float minRadius, bool deleteFibers) { if (minRadius<0) return true; vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Applying curvature threshold"; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); for (int i=0; iGetNumberOfCells(); i++) { ++disp ; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); // calculate curvatures vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j, p1); double p2[3]; points->GetPoint(j+1, p2); double p3[3]; points->GetPoint(j+2, p3); vnl_vector_fixed< float, 3 > v1, v2, v3; v1[0] = p2[0]-p1[0]; v1[1] = p2[1]-p1[1]; v1[2] = p2[2]-p1[2]; v2[0] = p3[0]-p2[0]; v2[1] = p3[1]-p2[1]; v2[2] = p3[2]-p2[2]; v3[0] = p1[0]-p3[0]; v3[1] = p1[1]-p3[1]; v3[2] = p1[2]-p3[2]; float a = v1.magnitude(); float b = v2.magnitude(); float c = v3.magnitude(); float r = a*b*c/std::sqrt((a+b+c)*(a+b-c)*(b+c-a)*(a-b+c)); // radius of triangle via Heron's formula (area of triangle) vtkIdType id = vtkNewPoints->InsertNextPoint(p1); container->GetPointIds()->InsertNextId(id); if (deleteFibers && rInsertNextCell(container); container = vtkSmartPointer::New(); } else if (j==numPoints-3) { id = vtkNewPoints->InsertNextPoint(p2); container->GetPointIds()->InsertNextId(id); id = vtkNewPoints->InsertNextPoint(p3); container->GetPointIds()->InsertNextId(id); vtkNewCells->InsertNextCell(container); } } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } bool mitk::FiberBundle::RemoveShortFibers(float lengthInMM) { MITK_INFO << "Removing short fibers"; if (lengthInMM<=0 || lengthInMMm_MaxFiberLength) // can't remove all fibers { MITK_WARN << "Process aborted. No fibers would be left!"; return false; } vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); float min = m_MaxFiberLength; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)>=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); if (m_FiberLengths.at(i)GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } bool mitk::FiberBundle::RemoveLongFibers(float lengthInMM) { if (lengthInMM<=0 || lengthInMM>m_MaxFiberLength) return true; if (lengthInMM vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Removing long fibers"; boost::progress_display disp(m_NumFibers); for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); if (m_FiberLengths.at(i)<=lengthInMM) { vtkSmartPointer container = vtkSmartPointer::New(); for (int j=0; jGetPoint(j); vtkIdType id = vtkNewPoints->InsertNextPoint(p); container->GetPointIds()->InsertNextId(id); } vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()<=0) return false; m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); return true; } void mitk::FiberBundle::ResampleSpline(float pointDistance, double tension, double continuity, double bias ) { if (pointDistance<=0) return; vtkSmartPointer vtkSmoothPoints = vtkSmartPointer::New(); //in smoothpoints the interpolated points representing a fiber are stored. //in vtkcells all polylines are stored, actually all id's of them are stored vtkSmartPointer vtkSmoothCells = vtkSmartPointer::New(); //cellcontainer for smoothed lines vtkIdType pointHelperCnt = 0; MITK_INFO << "Smoothing fibers"; vtkSmartPointer newFiberWeights = vtkSmartPointer::New(); newFiberWeights->SetName("FIBER_WEIGHTS"); newFiberWeights->SetNumberOfValues(m_NumFibers); boost::progress_display disp(m_NumFibers); #pragma omp parallel for for (int i=0; i newPoints = vtkSmartPointer::New(); float length = 0; float weight = 1; #pragma omp critical { length = m_FiberLengths.at(i); weight = m_FiberWeights->GetValue(i); ++disp; vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jInsertNextPoint(points->GetPoint(j)); } int sampling = std::ceil(length/pointDistance); vtkSmartPointer xSpline = vtkSmartPointer::New(); vtkSmartPointer ySpline = vtkSmartPointer::New(); vtkSmartPointer zSpline = vtkSmartPointer::New(); xSpline->SetDefaultBias(bias); xSpline->SetDefaultTension(tension); xSpline->SetDefaultContinuity(continuity); ySpline->SetDefaultBias(bias); ySpline->SetDefaultTension(tension); ySpline->SetDefaultContinuity(continuity); zSpline->SetDefaultBias(bias); zSpline->SetDefaultTension(tension); zSpline->SetDefaultContinuity(continuity); vtkSmartPointer spline = vtkSmartPointer::New(); spline->SetXSpline(xSpline); spline->SetYSpline(ySpline); spline->SetZSpline(zSpline); spline->SetPoints(newPoints); vtkSmartPointer functionSource = vtkSmartPointer::New(); functionSource->SetParametricFunction(spline); functionSource->SetUResolution(sampling); functionSource->SetVResolution(sampling); functionSource->SetWResolution(sampling); functionSource->Update(); vtkPolyData* outputFunction = functionSource->GetOutput(); vtkPoints* tmpSmoothPnts = outputFunction->GetPoints(); //smoothPoints of current fiber vtkSmartPointer smoothLine = vtkSmartPointer::New(); smoothLine->GetPointIds()->SetNumberOfIds(tmpSmoothPnts->GetNumberOfPoints()); #pragma omp critical { for (int j=0; jGetNumberOfPoints(); j++) { smoothLine->GetPointIds()->SetId(j, j+pointHelperCnt); vtkSmoothPoints->InsertNextPoint(tmpSmoothPnts->GetPoint(j)); } newFiberWeights->SetValue(vtkSmoothCells->GetNumberOfCells(), weight); vtkSmoothCells->InsertNextCell(smoothLine); pointHelperCnt += tmpSmoothPnts->GetNumberOfPoints(); } } SetFiberWeights(newFiberWeights); m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkSmoothPoints); m_FiberPolyData->SetLines(vtkSmoothCells); this->SetFiberPolyData(m_FiberPolyData, true); } void mitk::FiberBundle::ResampleSpline(float pointDistance) { ResampleSpline(pointDistance, 0, 0, 0 ); } unsigned long mitk::FiberBundle::GetNumberOfPoints() const { unsigned long points = 0; for (int i=0; iGetNumberOfCells(); i++) { vtkCell* cell = m_FiberPolyData->GetCell(i); points += cell->GetNumberOfPoints(); } return points; } void mitk::FiberBundle::Compress(float error) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Compressing fibers"; unsigned long numRemovedPoints = 0; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); vtkSmartPointer newFiberWeights = vtkSmartPointer::New(); newFiberWeights->SetName("FIBER_WEIGHTS"); newFiberWeights->SetNumberOfValues(m_NumFibers); #pragma omp parallel for for (int i=0; iGetNumberOfCells(); i++) { std::vector< vnl_vector_fixed< double, 3 > > vertices; float weight = 1; #pragma omp critical { ++disp; weight = m_FiberWeights->GetValue(i); vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, cand); vnl_vector_fixed< double, 3 > candV; candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2]; vertices.push_back(candV); } } // calculate curvatures int numPoints = vertices.size(); std::vector< int > removedPoints; removedPoints.resize(numPoints, 0); removedPoints[0]=-1; removedPoints[numPoints-1]=-1; vtkSmartPointer container = vtkSmartPointer::New(); int remCounter = 0; bool pointFound = true; while (pointFound) { pointFound = false; double minError = error; int removeIndex = -1; for (unsigned int j=0; j candV = vertices.at(j); int validP = -1; vnl_vector_fixed< double, 3 > pred; for (int k=j-1; k>=0; k--) if (removedPoints[k]<=0) { pred = vertices.at(k); validP = k; break; } int validS = -1; vnl_vector_fixed< double, 3 > succ; for (int k=j+1; k=0 && validS>=0) { double a = (candV-pred).magnitude(); double b = (candV-succ).magnitude(); double c = (pred-succ).magnitude(); double s=0.5*(a+b+c); double hc=(2.0/c)*sqrt(fabs(s*(s-a)*(s-b)*(s-c))); if (hcInsertNextPoint(vertices.at(j).data_block()); container->GetPointIds()->InsertNextId(id); } } } #pragma omp critical { newFiberWeights->SetValue(vtkNewCells->GetNumberOfCells(), weight); numRemovedPoints += remCounter; vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()>0) { MITK_INFO << "Removed points: " << numRemovedPoints; SetFiberWeights(newFiberWeights); m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } } void mitk::FiberBundle::ResampleLinear(double pointDistance) { vtkSmartPointer vtkNewPoints = vtkSmartPointer::New(); vtkSmartPointer vtkNewCells = vtkSmartPointer::New(); MITK_INFO << "Resampling fibers (linear)"; boost::progress_display disp(m_FiberPolyData->GetNumberOfCells()); vtkSmartPointer newFiberWeights = vtkSmartPointer::New(); newFiberWeights->SetName("FIBER_WEIGHTS"); newFiberWeights->SetNumberOfValues(m_NumFibers); #pragma omp parallel for for (int i=0; iGetNumberOfCells(); i++) { std::vector< vnl_vector_fixed< double, 3 > > vertices; float weight = 1; #pragma omp critical { ++disp; weight = m_FiberWeights->GetValue(i); vtkCell* cell = m_FiberPolyData->GetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); for (int j=0; jGetPoint(j, cand); vnl_vector_fixed< double, 3 > candV; candV[0]=cand[0]; candV[1]=cand[1]; candV[2]=cand[2]; vertices.push_back(candV); } } vtkSmartPointer container = vtkSmartPointer::New(); vnl_vector_fixed< double, 3 > lastV = vertices.at(0); #pragma omp critical { vtkIdType id = vtkNewPoints->InsertNextPoint(lastV.data_block()); container->GetPointIds()->InsertNextId(id); } for (unsigned int j=1; j vec = vertices.at(j) - lastV; double new_dist = vec.magnitude(); if (new_dist >= pointDistance) { vnl_vector_fixed< double, 3 > newV = lastV; if ( new_dist-pointDistance <= mitk::eps ) { vec.normalize(); newV += vec * pointDistance; } else { // intersection between sphere (radius 'pointDistance', center 'lastV') and line (direction 'd' and point 'p') vnl_vector_fixed< double, 3 > p = vertices.at(j-1); vnl_vector_fixed< double, 3 > d = vertices.at(j) - p; double a = d[0]*d[0] + d[1]*d[1] + d[2]*d[2]; double b = 2 * (d[0] * (p[0] - lastV[0]) + d[1] * (p[1] - lastV[1]) + d[2] * (p[2] - lastV[2])); double c = (p[0] - lastV[0])*(p[0] - lastV[0]) + (p[1] - lastV[1])*(p[1] - lastV[1]) + (p[2] - lastV[2])*(p[2] - lastV[2]) - pointDistance*pointDistance; double v1 =(-b + std::sqrt(b*b-4*a*c))/(2*a); double v2 =(-b - std::sqrt(b*b-4*a*c))/(2*a); if (v1>0) newV = p + d * v1; else if (v2>0) newV = p + d * v2; else MITK_INFO << "ERROR1 - linear resampling"; j--; } #pragma omp critical { vtkIdType id = vtkNewPoints->InsertNextPoint(newV.data_block()); container->GetPointIds()->InsertNextId(id); } lastV = newV; } else if (j==vertices.size()-1 && new_dist>0.0001) { #pragma omp critical { vtkIdType id = vtkNewPoints->InsertNextPoint(vertices.at(j).data_block()); container->GetPointIds()->InsertNextId(id); } } } #pragma omp critical { newFiberWeights->SetValue(vtkNewCells->GetNumberOfCells(), weight); vtkNewCells->InsertNextCell(container); } } if (vtkNewCells->GetNumberOfCells()>0) { SetFiberWeights(newFiberWeights); m_FiberPolyData = vtkSmartPointer::New(); m_FiberPolyData->SetPoints(vtkNewPoints); m_FiberPolyData->SetLines(vtkNewCells); this->SetFiberPolyData(m_FiberPolyData, true); } } // reapply selected colorcoding in case PolyData structure has changed bool mitk::FiberBundle::Equals(mitk::FiberBundle* fib, double eps) { if (fib==nullptr) { MITK_INFO << "Reference bundle is nullptr!"; return false; } if (m_NumFibers!=fib->GetNumFibers()) { MITK_INFO << "Unequal number of fibers!"; MITK_INFO << m_NumFibers << " vs. " << fib->GetNumFibers(); return false; } for (int i=0; iGetCell(i); int numPoints = cell->GetNumberOfPoints(); vtkPoints* points = cell->GetPoints(); vtkCell* cell2 = fib->GetFiberPolyData()->GetCell(i); int numPoints2 = cell2->GetNumberOfPoints(); vtkPoints* points2 = cell2->GetPoints(); if (numPoints2!=numPoints) { MITK_INFO << "Unequal number of points in fiber " << i << "!"; MITK_INFO << numPoints2 << " vs. " << numPoints; return false; } for (int j=0; jGetPoint(j); double* p2 = points2->GetPoint(j); if (fabs(p1[0]-p2[0])>eps || fabs(p1[1]-p2[1])>eps || fabs(p1[2]-p2[2])>eps) { MITK_INFO << "Unequal points in fiber " << i << " at position " << j << "!"; MITK_INFO << "p1: " << p1[0] << ", " << p1[1] << ", " << p1[2]; MITK_INFO << "p2: " << p2[0] << ", " << p2[1] << ", " << p2[2]; return false; } } } return true; } void mitk::FiberBundle::PrintSelf(std::ostream &os, itk::Indent indent) const { os << indent << this->GetNameOfClass() << ":\n"; os << indent << "Number of fibers: " << this->GetNumFibers() << std::endl; os << indent << "Min. fiber length: " << this->GetMinFiberLength() << std::endl; os << indent << "Max. fiber length: " << this->GetMaxFiberLength() << std::endl; os << indent << "Mean fiber length: " << this->GetMeanFiberLength() << std::endl; os << indent << "Median fiber length: " << this->GetMedianFiberLength() << std::endl; os << indent << "STDEV fiber length: " << this->GetLengthStDev() << std::endl; os << indent << "Number of points: " << this->GetNumberOfPoints() << std::endl; Superclass::PrintSelf(os, indent); } /* ESSENTIAL IMPLEMENTATION OF SUPERCLASS METHODS */ void mitk::FiberBundle::UpdateOutputInformation() { } void mitk::FiberBundle::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::FiberBundle::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool mitk::FiberBundle::VerifyRequestedRegion() { return true; } void mitk::FiberBundle::SetRequestedRegion(const itk::DataObject* ) { } diff --git a/Modules/Gizmo/src/mitkGizmoMapper2D.cpp b/Modules/Gizmo/src/mitkGizmoMapper2D.cpp index 39fe9bb696..d0703db556 100644 --- a/Modules/Gizmo/src/mitkGizmoMapper2D.cpp +++ b/Modules/Gizmo/src/mitkGizmoMapper2D.cpp @@ -1,341 +1,341 @@ /*=================================================================== 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 "mitkGizmoMapper2D.h" #include "mitkGizmo.h" // MITK includes #include #include #include #include #include // VTK includes #include #include #include #include #include #include #include #include #include mitk::GizmoMapper2D::LocalStorage::LocalStorage() { - m_VtkPolyDataMapper = vtkSmartPointer::New(); + m_VtkPolyDataMapper = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); m_Actor->SetMapper(m_VtkPolyDataMapper); } const mitk::Gizmo *mitk::GizmoMapper2D::GetInput() { return static_cast(GetDataNode()->GetData()); } void mitk::GizmoMapper2D::ResetMapper(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); ls->m_Actor->VisibilityOff(); } namespace { //! Helper method: will assign given value to all points in given polydata object. void AssignScalarValueTo(vtkPolyData *polydata, char value) { vtkSmartPointer pointData = vtkSmartPointer::New(); int numberOfPoints = polydata->GetNumberOfPoints(); pointData->SetNumberOfComponents(1); pointData->SetNumberOfTuples(numberOfPoints); pointData->FillComponent(0, value); polydata->GetPointData()->SetScalars(pointData); } //! Helper method: will create a vtkPolyData representing a disk //! around center, inside the plane defined by viewRight and viewUp, //! and with the given radius. vtkSmartPointer Create2DDisk(mitk::Vector3D viewRight, mitk::Vector3D viewUp, mitk::Point3D center, double radius) { // build the axis itself (as a tube around the line defining the axis) vtkSmartPointer disk = vtkSmartPointer::New(); mitk::Vector3D ringPointer; unsigned int numberOfRingPoints = 36; vtkSmartPointer ringPoints = vtkSmartPointer::New(); vtkSmartPointer ringPoly = vtkSmartPointer::New(); ringPoly->InsertNextCell(numberOfRingPoints + 1); for (unsigned int segment = 0; segment < numberOfRingPoints; ++segment) { double x = std::cos((double)(segment) / (double)numberOfRingPoints * 2.0 * vtkMath::Pi()); double y = std::sin((double)(segment) / (double)numberOfRingPoints * 2.0 * vtkMath::Pi()); ringPointer = viewRight * x + viewUp * y; ringPoints->InsertPoint(segment, (center + ringPointer * radius).GetDataPointer()); ringPoly->InsertCellPoint(segment); } ringPoly->InsertCellPoint(0); disk->SetPoints(ringPoints); disk->SetPolys(ringPoly); return disk; } //! Helper method: will create a vtkPolyData representing a 2D arrow //! that is oriented from arrowStart to arrowTip, orthogonal //! to camera direction. The arrow tip will contain scalar values //! of vertexValueScale, the arrow shaft will contain scalar values //! of vertexValueMove. Those values are used for picking during interaction. vtkSmartPointer Create2DArrow(mitk::Vector3D cameraDirection, mitk::Point3D arrowStart, mitk::Point3D arrowTip, int vertexValueMove, int vertexValueScale) { mitk::Vector3D arrowDirection = arrowTip - arrowStart; mitk::Vector3D arrowOrthogonal = itk::CrossProduct(cameraDirection, arrowDirection); arrowOrthogonal.Normalize(); double triangleFraction = 0.2; vtkSmartPointer arrow = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); // shaft : points 0, 1 points->InsertPoint(0, arrowStart.GetDataPointer()); points->InsertPoint(1, (arrowStart + arrowDirection * (1.0 - triangleFraction)).GetDataPointer()); // tip : points 2, 3, 4 points->InsertPoint(2, arrowTip.GetDataPointer()); points->InsertPoint(3, (arrowStart + (1.0 - triangleFraction) * arrowDirection + arrowOrthogonal * (0.5 * triangleFraction * arrowDirection.GetNorm())) .GetDataPointer()); points->InsertPoint(4, (arrowStart + (1.0 - triangleFraction) * arrowDirection - arrowOrthogonal * (0.5 * triangleFraction * arrowDirection.GetNorm())) .GetDataPointer()); arrow->SetPoints(points); // define line connection for shaft vtkSmartPointer lines = vtkSmartPointer::New(); vtkIdType shaftLinePoints[] = {0, 1}; lines->InsertNextCell(2, shaftLinePoints); arrow->SetLines(lines); // define polygon for triangle vtkSmartPointer polys = vtkSmartPointer::New(); vtkIdType tipLinePoints[] = {2, 3, 4}; polys->InsertNextCell(3, tipLinePoints); arrow->SetPolys(polys); // assign scalar values vtkSmartPointer pointData = vtkSmartPointer::New(); pointData->SetNumberOfComponents(1); pointData->SetNumberOfTuples(5); pointData->FillComponent(0, vertexValueScale); pointData->SetTuple1(0, vertexValueMove); pointData->SetTuple1(1, vertexValueMove); arrow->GetPointData()->SetScalars(pointData); return arrow; } } vtkPolyData *mitk::GizmoMapper2D::GetVtkPolyData(mitk::BaseRenderer *renderer) { return m_LSH.GetLocalStorage(renderer)->m_VtkPolyDataMapper->GetInput(); } void mitk::GizmoMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { auto gizmo = GetInput(); auto node = GetDataNode(); LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // check if something important has changed and we need to re-render if ((ls->m_LastUpdateTime >= node->GetMTime()) && (ls->m_LastUpdateTime >= gizmo->GetPipelineMTime()) && (ls->m_LastUpdateTime >= renderer->GetCurrentWorldPlaneGeometryUpdateTime()) && (ls->m_LastUpdateTime >= renderer->GetCurrentWorldPlaneGeometry()->GetMTime()) && (ls->m_LastUpdateTime >= node->GetPropertyList()->GetMTime()) && (ls->m_LastUpdateTime >= node->GetPropertyList(renderer)->GetMTime())) { return; } ls->m_LastUpdateTime.Modified(); // some special handling around visibility: let two properties steer // visibility in 2D instead of many renderer specific "visible" properties bool visible2D = true; this->GetDataNode()->GetBoolProperty("show in 2D", visible2D); if (!visible2D && renderer->GetMapperID() == BaseRenderer::Standard2D) { ls->m_Actor->VisibilityOff(); return; } else { ls->m_Actor->VisibilityOn(); } auto camera = renderer->GetVtkRenderer()->GetActiveCamera(); auto plane = renderer->GetCurrentWorldPlaneGeometry(); Point3D gizmoCenterView = plane->ProjectPointOntoPlane(gizmo->GetCenter()); Vector3D viewUp; camera->GetViewUp(viewUp.GetDataPointer()); Vector3D cameraDirection; camera->GetDirectionOfProjection(cameraDirection.GetDataPointer()); Vector3D viewRight = itk::CrossProduct(viewUp, cameraDirection); auto appender = vtkSmartPointer::New(); double diagonal = std::min(renderer->GetSizeX(), renderer->GetSizeY()); double arrowLength = 0.1 * diagonal; // fixed in relation to window size auto disk = Create2DDisk(viewRight, viewUp, gizmoCenterView - cameraDirection, 0.1 * arrowLength); AssignScalarValueTo(disk, Gizmo::MoveFreely); appender->AddInputData(disk); // loop over directions -1 and +1 for arrows for (double direction = -1.0; direction < 2.0; direction += 2.0) { auto axisX = Create2DArrow(cameraDirection, gizmoCenterView, plane->ProjectPointOntoPlane(gizmo->GetCenter() + (gizmo->GetAxisX() * arrowLength) * direction), Gizmo::MoveAlongAxisX, Gizmo::ScaleX); appender->AddInputData(axisX); auto axisY = Create2DArrow(cameraDirection, gizmoCenterView, plane->ProjectPointOntoPlane(gizmo->GetCenter() + (gizmo->GetAxisY() * arrowLength) * direction), Gizmo::MoveAlongAxisY, Gizmo::ScaleY); appender->AddInputData(axisY); auto axisZ = Create2DArrow(cameraDirection, gizmoCenterView, plane->ProjectPointOntoPlane(gizmo->GetCenter() + (gizmo->GetAxisZ() * arrowLength) * direction), Gizmo::MoveAlongAxisZ, Gizmo::ScaleZ); appender->AddInputData(axisZ); } ls->m_VtkPolyDataMapper->SetInputConnection(appender->GetOutputPort()); ApplyVisualProperties(renderer); } void mitk::GizmoMapper2D::ApplyVisualProperties(BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); float lineWidth = 3.0f; ls->m_Actor->GetProperty()->SetLineWidth(lineWidth); mitk::LookupTableProperty::Pointer lookupTableProp; this->GetDataNode()->GetProperty(lookupTableProp, "LookupTable", renderer); if (lookupTableProp.IsNotNull()) { ls->m_VtkPolyDataMapper->SetLookupTable(lookupTableProp->GetLookupTable()->GetVtkLookupTable()); } bool scalarVisibility = false; this->GetDataNode()->GetBoolProperty("scalar visibility", scalarVisibility); ls->m_VtkPolyDataMapper->SetScalarVisibility((scalarVisibility ? 1 : 0)); if (scalarVisibility) { mitk::VtkScalarModeProperty *scalarMode; if (this->GetDataNode()->GetProperty(scalarMode, "scalar mode", renderer)) ls->m_VtkPolyDataMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); else ls->m_VtkPolyDataMapper->SetScalarModeToDefault(); bool colorMode = false; this->GetDataNode()->GetBoolProperty("color mode", colorMode); ls->m_VtkPolyDataMapper->SetColorMode((colorMode ? 1 : 0)); double scalarsMin = 0; this->GetDataNode()->GetDoubleProperty("ScalarsRangeMinimum", scalarsMin, renderer); double scalarsMax = 1.0; this->GetDataNode()->GetDoubleProperty("ScalarsRangeMaximum", scalarsMax, renderer); ls->m_VtkPolyDataMapper->SetScalarRange(scalarsMin, scalarsMax); } } void mitk::GizmoMapper2D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer /*= nullptr*/, bool /*= false*/) { node->SetProperty("color", ColorProperty::New(0.3, 0.3, 0.3)); // a little lighter than the // "plane widgets" of // QmitkStdMultiWidget node->SetProperty("scalar visibility", BoolProperty::New(true), renderer); node->SetProperty("ScalarsRangeMinimum", DoubleProperty::New(0), renderer); node->SetProperty("ScalarsRangeMaximum", DoubleProperty::New((int)Gizmo::NoHandle), renderer); double colorMoveFreely[] = {1, 0, 0, 1}; // RGBA double colorAxisX[] = {0.753, 0, 0, 1}; // colors copied from QmitkStdMultiWidget to double colorAxisY[] = {0, 0.69, 0, 1}; // look alike double colorAxisZ[] = {0, 0.502, 1, 1}; double colorInactive[] = {0.7, 0.7, 0.7, 1}; // build a nice color table vtkSmartPointer lut = vtkSmartPointer::New(); lut->SetNumberOfTableValues((int)Gizmo::NoHandle + 1); lut->SetTableRange(0, (int)Gizmo::NoHandle); lut->SetTableValue(Gizmo::MoveFreely, colorMoveFreely); lut->SetTableValue(Gizmo::MoveAlongAxisX, colorAxisX); lut->SetTableValue(Gizmo::MoveAlongAxisY, colorAxisY); lut->SetTableValue(Gizmo::MoveAlongAxisZ, colorAxisZ); lut->SetTableValue(Gizmo::RotateAroundAxisX, colorAxisX); lut->SetTableValue(Gizmo::RotateAroundAxisY, colorAxisY); lut->SetTableValue(Gizmo::RotateAroundAxisZ, colorAxisZ); lut->SetTableValue(Gizmo::ScaleX, colorAxisX); lut->SetTableValue(Gizmo::ScaleY, colorAxisY); lut->SetTableValue(Gizmo::ScaleZ, colorAxisZ); lut->SetTableValue(Gizmo::NoHandle, colorInactive); mitk::LookupTable::Pointer mlut = mitk::LookupTable::New(); mlut->SetVtkLookupTable(lut); mitk::LookupTableProperty::Pointer lutProp = mitk::LookupTableProperty::New(); lutProp->SetLookupTable(mlut); node->SetProperty("LookupTable", lutProp, renderer); node->SetProperty("helper object", BoolProperty::New(true), renderer); node->SetProperty("visible", BoolProperty::New(true), renderer); node->SetProperty("show in 2D", BoolProperty::New(true), renderer); // no "show in 3D" because this would require a specialized mapper for gizmos in 3D } diff --git a/Modules/Gizmo/src/mitkGizmoMapper2D.h b/Modules/Gizmo/src/mitkGizmoMapper2D.h index 14b4f2834e..83b5e6b59a 100644 --- a/Modules/Gizmo/src/mitkGizmoMapper2D.h +++ b/Modules/Gizmo/src/mitkGizmoMapper2D.h @@ -1,97 +1,97 @@ /*=================================================================== 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 mitkGizmoMapper2D_h #define mitkGizmoMapper2D_h #include -#include +#include namespace mitk { // forward declaration class Gizmo; //! 2D Mapper for mitk::Gimzo. //! //! Paints a similar representation as for 2D (see mitk::Gizmo itself). //! The three axes of the manipulated object are visualized. They are //! pickable and will report "move along axis" or "scale" when clicked //! at the arrow shafts or the arrow tips. //! //! For usability, we removed the circles for rotation because they //! would most often coincide with the arrows, thus distinction is //! complicated. class GizmoMapper2D : public mitk::VtkMapper { public: mitkClassMacro(GizmoMapper2D, VtkMapper); itkFactorylessNewMacro(Self); itkCloneMacro(Self); //! Provides given node with a set of default properties. //! //! \param node The DataNode to decorate with properties. //! \param renderer When not nullptr, generate specific properties for given renderer //! \param overwrite Whether already existing properties shall be overwritten. static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer = nullptr, bool overwrite = false); //! Return the vtkProp that represents the "rendering result". vtkProp *GetVtkProp(mitk::BaseRenderer *renderer) override { return m_LSH.GetLocalStorage(renderer)->m_Actor; } //! "Resets" the mapper, setting its result to invisible. void ResetMapper(mitk::BaseRenderer *renderer) override; //! Return the internal vtkPolyData for given renderer. //! This serves for picking by the associated interactor class. vtkPolyData *GetVtkPolyData(mitk::BaseRenderer *renderer); private: //! Provide the mapping input as a specific RawMesh_C const Gizmo *GetInput(); //! Update the vtkProp, i.e. the contours of a slice through our RawMesh_C. virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override; //! Apply visual properties void ApplyVisualProperties(BaseRenderer *renderer); //! (RenderWindow) Instance specific data. class LocalStorage : public Mapper::BaseLocalStorage { public: //! The overall rendering result. vtkSmartPointer m_Actor; //! The mapper of the resulting vtkPolyData //! (3D polygons for 3D mapper, 2D contours for 2D mapper) - vtkSmartPointer m_VtkPolyDataMapper; + vtkSmartPointer m_VtkPolyDataMapper; //! Last time this storage has been updated. itk::TimeStamp m_LastUpdateTime; LocalStorage(); }; //! (RenderWindow) Instance specific data. LocalStorageHandler m_LSH; }; } // namespace #endif diff --git a/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp b/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp index 1913da91dc..c5871d1a1a 100644 --- a/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp +++ b/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp @@ -1,184 +1,184 @@ /*=================================================================== 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 "mitkIOExtObjectFactory.h" #include "mitkCoreObjectFactory.h" #include "mitkParRecFileIOFactory.h" //#include "mitkObjFileIOFactory.h" #include "mitkStlVolumeTimeSeriesIOFactory.h" #include "mitkVtkVolumeTimeSeriesIOFactory.h" #include "mitkUnstructuredGridVtkWriter.h" #include "mitkUnstructuredGridVtkWriterFactory.h" -#include "mitkGPUVolumeMapper3D.h" +#include "mitkVolumeMapperVtkSmart3D.h" #include "mitkMesh.h" #include "mitkMeshMapper2D.h" #include "mitkMeshVtkMapper3D.h" #include "mitkUnstructuredGridMapper2D.h" #include "mitkUnstructuredGridVtkMapper3D.h" #include "mitkVtkGLMapperWrapper.h" #include #include #include mitk::IOExtObjectFactory::IOExtObjectFactory() : CoreObjectFactoryBase(), m_ParRecFileIOFactory(ParRecFileIOFactory::New().GetPointer()) //, m_ObjFileIOFactory(ObjFileIOFactory::New().GetPointer()) , m_StlVolumeTimeSeriesIOFactory(StlVolumeTimeSeriesIOFactory::New().GetPointer()), m_VtkVolumeTimeSeriesIOFactory(VtkVolumeTimeSeriesIOFactory::New().GetPointer()), m_UnstructuredGridVtkWriterFactory(UnstructuredGridVtkWriterFactory::New().GetPointer()) { static bool alreadyDone = false; if (!alreadyDone) { MITK_DEBUG << "IOExtObjectFactory c'tor" << std::endl; itk::ObjectFactoryBase::RegisterFactory(m_ParRecFileIOFactory); itk::ObjectFactoryBase::RegisterFactory(m_StlVolumeTimeSeriesIOFactory); itk::ObjectFactoryBase::RegisterFactory(m_VtkVolumeTimeSeriesIOFactory); itk::ObjectFactoryBase::RegisterFactory(m_UnstructuredGridVtkWriterFactory); m_FileWriters.push_back(mitk::UnstructuredGridVtkWriter::New().GetPointer()); m_FileWriters.push_back(mitk::UnstructuredGridVtkWriter::New().GetPointer()); m_FileWriters.push_back(mitk::UnstructuredGridVtkWriter::New().GetPointer()); CreateFileExtensionsMap(); alreadyDone = true; } } mitk::IOExtObjectFactory::~IOExtObjectFactory() { itk::ObjectFactoryBase::UnRegisterFactory(m_ParRecFileIOFactory); itk::ObjectFactoryBase::UnRegisterFactory(m_StlVolumeTimeSeriesIOFactory); itk::ObjectFactoryBase::UnRegisterFactory(m_VtkVolumeTimeSeriesIOFactory); itk::ObjectFactoryBase::UnRegisterFactory(m_UnstructuredGridVtkWriterFactory); } mitk::Mapper::Pointer mitk::IOExtObjectFactory::CreateMapper(mitk::DataNode *node, MapperSlotId id) { mitk::Mapper::Pointer newMapper = nullptr; mitk::BaseData *data = node->GetData(); if (id == mitk::BaseRenderer::Standard2D) { if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::MeshMapper2D::New(); newMapper->SetDataNode(node); } else if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::VtkGLMapperWrapper::New(mitk::UnstructuredGridMapper2D::New().GetPointer()); newMapper->SetDataNode(node); } } else if (id == mitk::BaseRenderer::Standard3D) { if ((dynamic_cast(data) != nullptr)) { - newMapper = mitk::GPUVolumeMapper3D::New(); + newMapper = mitk::VolumeMapperVtkSmart3D::New(); newMapper->SetDataNode(node); } else if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::MeshVtkMapper3D::New(); newMapper->SetDataNode(node); } else if ((dynamic_cast(data) != nullptr)) { newMapper = mitk::UnstructuredGridVtkMapper3D::New(); newMapper->SetDataNode(node); } } return newMapper; } void mitk::IOExtObjectFactory::SetDefaultProperties(mitk::DataNode *node) { if (node == nullptr) return; mitk::DataNode::Pointer nodePointer = node; mitk::Image::Pointer image = dynamic_cast(node->GetData()); if (image.IsNotNull() && image->IsInitialized()) { - mitk::GPUVolumeMapper3D::SetDefaultProperties(node); + mitk::VolumeMapperVtkSmart3D::SetDefaultProperties(node); } if (dynamic_cast(node->GetData())) { mitk::UnstructuredGridVtkMapper3D::SetDefaultProperties(node); } } const char *mitk::IOExtObjectFactory::GetFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_FileExtensionsMap, fileExtension); return fileExtension.c_str(); } mitk::CoreObjectFactoryBase::MultimapType mitk::IOExtObjectFactory::GetFileExtensionsMap() { return m_FileExtensionsMap; } mitk::CoreObjectFactoryBase::MultimapType mitk::IOExtObjectFactory::GetSaveFileExtensionsMap() { return m_SaveFileExtensionsMap; } void mitk::IOExtObjectFactory::CreateFileExtensionsMap() { m_FileExtensionsMap.insert(std::pair("*.vtu", "VTK Unstructured Grid")); m_FileExtensionsMap.insert(std::pair("*.vtk", "VTK Unstructured Grid")); m_FileExtensionsMap.insert(std::pair("*.pvtu", "VTK Unstructured Grid")); m_SaveFileExtensionsMap.insert(std::pair("*.pvtu", "VTK Parallel XML Unstructured Grid")); m_SaveFileExtensionsMap.insert(std::pair("*.vtu", "VTK XML Unstructured Grid")); m_SaveFileExtensionsMap.insert(std::pair("*.vtk", "VTK Legacy Unstructured Grid")); } const char *mitk::IOExtObjectFactory::GetSaveFileExtensions() { std::string fileExtension; this->CreateFileExtensions(m_SaveFileExtensionsMap, fileExtension); return fileExtension.c_str(); } struct RegisterIOExtObjectFactory { RegisterIOExtObjectFactory() : m_Factory(mitk::IOExtObjectFactory::New()) { mitk::CoreObjectFactory::GetInstance()->RegisterExtraFactory(m_Factory); } ~RegisterIOExtObjectFactory() { mitk::CoreObjectFactory::GetInstance()->UnRegisterExtraFactory(m_Factory); } mitk::IOExtObjectFactory::Pointer m_Factory; }; static RegisterIOExtObjectFactory registerIOExtObjectFactory; diff --git a/Modules/MapperExt/files.cmake b/Modules/MapperExt/files.cmake index 6a072e68b7..3ec5ef80f6 100644 --- a/Modules/MapperExt/files.cmake +++ b/Modules/MapperExt/files.cmake @@ -1,21 +1,20 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkEnhancedPointSetVtkMapper3D.cpp mitkGPUVolumeMapper3D.cpp mitkMeshMapper2D.cpp mitkMeshVtkMapper3D.cpp mitkSplineVtkMapper3D.cpp mitkUnstructuredGridMapper2D.cpp mitkUnstructuredGridVtkMapper3D.cpp mitkVectorImageMapper2D.cpp + mitkVolumeMapperVtkSmart3D.cpp vtkMaskedGlyph2D.cpp vtkMaskedGlyph3D.cpp vtkMitkGPUVolumeRayCastMapper.cpp - vtkMitkOpenGLVolumeTextureMapper3D.cpp - vtkMitkVolumeTextureMapper3D.cpp vtkUnstructuredGridMapper.cpp vtkPointSetSlicer.cxx ) diff --git a/Modules/MapperExt/include/mitkGPUVolumeMapper3D.h b/Modules/MapperExt/include/mitkGPUVolumeMapper3D.h index 69067f71a8..07845fc4fa 100644 --- a/Modules/MapperExt/include/mitkGPUVolumeMapper3D.h +++ b/Modules/MapperExt/include/mitkGPUVolumeMapper3D.h @@ -1,190 +1,164 @@ /*=================================================================== 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 MITKGPUVOLUMEMAPPER3D_H_HEADER_INCLUDED #define MITKGPUVOLUMEMAPPER3D_H_HEADER_INCLUDED // MITK #include "MitkMapperExtExports.h" #include "mitkBaseRenderer.h" #include "mitkCommon.h" #include "mitkImage.h" #include "mitkVtkMapper.h" -#include "vtkMitkVolumeTextureMapper3D.h" // VTK #include #include #include #include #include #include -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) - #include "vtkMitkGPUVolumeRayCastMapper.h" -#endif - namespace mitk { /************************************************************************/ /* Properties that influence the mapper are: * * - \b "level window": for the level window of the volume data * - \b "LookupTable" : for the lookup table of the volume data * - \b "TransferFunction" (mitk::TransferFunctionProperty): for the used transfer function of the volume data ************************************************************************/ //##Documentation //## @brief Vtk-based mapper for VolumeData //## //## @ingroup Mapper class MITKMAPPEREXT_EXPORT GPUVolumeMapper3D : public VtkMapper { public: mitkClassMacro(GPUVolumeMapper3D, VtkMapper); itkFactorylessNewMacro(Self) itkCloneMacro(Self) virtual const mitk::Image *GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer) override; virtual void ApplyProperties(vtkActor *actor, mitk::BaseRenderer *renderer) override; static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer = nullptr, bool overwrite = false); /** Returns true if this Mapper currently allows for Level-of-Detail rendering. * This reflects whether this Mapper currently invokes StartEvent, EndEvent, and * ProgressEvent on BaseRenderer. */ virtual bool IsLODEnabled(BaseRenderer *renderer = nullptr) const override; bool IsMIPEnabled(BaseRenderer *renderer = nullptr); bool IsGPUEnabled(BaseRenderer *renderer = nullptr); bool IsRAYEnabled(BaseRenderer *renderer = nullptr); virtual void MitkRenderVolumetricGeometry(mitk::BaseRenderer *renderer) override; protected: GPUVolumeMapper3D(); virtual ~GPUVolumeMapper3D(); bool IsRenderable(mitk::BaseRenderer *renderer); void InitCommon(); void DeinitCommon(); void InitCPU(mitk::BaseRenderer *renderer); void DeinitCPU(mitk::BaseRenderer *renderer); void GenerateDataCPU(mitk::BaseRenderer *renderer); bool InitGPU(mitk::BaseRenderer *renderer); - void DeinitGPU(mitk::BaseRenderer *renderer); - void GenerateDataGPU(mitk::BaseRenderer *renderer); - -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) + void DeinitGPU(mitk::BaseRenderer *); + void GenerateDataGPU(mitk::BaseRenderer *); bool InitRAY(mitk::BaseRenderer *renderer); void DeinitRAY(mitk::BaseRenderer *renderer); void GenerateDataRAY(mitk::BaseRenderer *renderer); -#endif - void InitVtkMapper(mitk::BaseRenderer *renderer); virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override; void CreateDefaultTransferFunctions(); void UpdateTransferFunctions(mitk::BaseRenderer *renderer); vtkSmartPointer m_Volumenullptr; bool m_commonInitialized; vtkSmartPointer m_UnitSpacingImageFilter; vtkSmartPointer m_DefaultOpacityTransferFunction; vtkSmartPointer m_DefaultGradientTransferFunction; vtkSmartPointer m_DefaultColorTransferFunction; vtkSmartPointer m_BinaryOpacityTransferFunction; vtkSmartPointer m_BinaryGradientTransferFunction; vtkSmartPointer m_BinaryColorTransferFunction; class LocalStorage : public mitk::Mapper::BaseLocalStorage { public: // NO SMARTPOINTER HERE vtkRenderWindow *m_VtkRenderWindow; bool m_cpuInitialized; vtkSmartPointer m_VolumeCPU; vtkSmartPointer m_MapperCPU; vtkSmartPointer m_VolumePropertyCPU; bool m_gpuSupported; bool m_gpuInitialized; vtkSmartPointer m_VolumeGPU; - vtkSmartPointer m_MapperGPU; vtkSmartPointer m_VolumePropertyGPU; -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) - bool m_raySupported; bool m_rayInitialized; vtkSmartPointer m_VolumeRAY; vtkSmartPointer m_MapperRAY; vtkSmartPointer m_VolumePropertyRAY; -#endif - LocalStorage() { m_VtkRenderWindow = 0; m_cpuInitialized = false; m_gpuInitialized = false; m_gpuSupported = true; // assume initially gpu slicing is supported -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) m_rayInitialized = false; m_raySupported = true; // assume initially gpu raycasting is supported -#endif } ~LocalStorage() { if (m_cpuInitialized && m_MapperCPU && m_VtkRenderWindow) m_MapperCPU->ReleaseGraphicsResources(m_VtkRenderWindow); - if (m_gpuInitialized && m_MapperGPU && m_VtkRenderWindow) - m_MapperGPU->ReleaseGraphicsResources(m_VtkRenderWindow); - -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) if (m_rayInitialized && m_MapperRAY && m_VtkRenderWindow) m_MapperRAY->ReleaseGraphicsResources(m_VtkRenderWindow); -#endif } }; mitk::LocalStorageHandler m_LSH; }; } // namespace mitk #endif /* MITKVOLUMEDATAVTKMAPPER3D_H_HEADER_INCLUDED */ diff --git a/Modules/MapperExt/include/mitkVolumeMapperVtkSmart3D.h b/Modules/MapperExt/include/mitkVolumeMapperVtkSmart3D.h new file mode 100644 index 0000000000..46af198c5b --- /dev/null +++ b/Modules/MapperExt/include/mitkVolumeMapperVtkSmart3D.h @@ -0,0 +1,75 @@ +/*=================================================================== + +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 MITKVTKSMARTVOLUMEMAPPER_H_HEADER_INCLUDED +#define MITKVTKSMARTVOLUMEMAPPER_H_HEADER_INCLUDED + +// MITK +#include "MitkMapperExtExports.h" +#include "mitkBaseRenderer.h" +#include "mitkCommon.h" +#include "mitkImage.h" +#include "mitkVtkMapper.h" + +// VTK +#include +#include +#include +#include +#include +#include + +namespace mitk +{ + + //##Documentation + //## @brief Vtk-based mapper for VolumeData + //## + //## @ingroup Mapper + class MITKMAPPEREXT_EXPORT VolumeMapperVtkSmart3D : public VtkMapper + { + public: + mitkClassMacro(VolumeMapperVtkSmart3D, VtkMapper); + + itkFactorylessNewMacro(Self) itkCloneMacro(Self) + + virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer) override; + + virtual void ApplyProperties(vtkActor *actor, mitk::BaseRenderer *renderer) override; + static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer = nullptr, bool overwrite = false); + + protected: + VolumeMapperVtkSmart3D(); + virtual ~VolumeMapperVtkSmart3D(); + + virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override; + + void createMapper(vtkImageData*); + void createVolume(); + void createVolumeProperty(); + vtkImageData* GetInputImage(); + + vtkSmartPointer m_Volume; + vtkSmartPointer m_SmartVolumeMapper; + vtkSmartPointer m_VolumeProperty; + + void UpdateTransferFunctions(mitk::BaseRenderer *renderer); + void UpdateRenderMode(mitk::BaseRenderer *renderer); + }; + +} // namespace mitk + +#endif /* MITKVTKSMARTVOLUMEMAPPER_H_HEADER_INCLUDED */ diff --git a/Modules/MapperExt/include/vtkMitkGPUVolumeRayCastMapper.h b/Modules/MapperExt/include/vtkMitkGPUVolumeRayCastMapper.h index cf37c3bb21..a7a6031c65 100644 --- a/Modules/MapperExt/include/vtkMitkGPUVolumeRayCastMapper.h +++ b/Modules/MapperExt/include/vtkMitkGPUVolumeRayCastMapper.h @@ -1,299 +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. ===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper.h,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ // .NAME vtkMitkGPUVolumeRayCastMapper - Ray casting performed on the GPU. // .SECTION Description // vtkMitkGPUVolumeRayCastMapper is a volume mapper that performs ray casting on // the GPU using fragment programs. // #ifndef __vtkMitkGPUVolumeRayCastMapper_h #define __vtkMitkGPUVolumeRayCastMapper_h #include "MitkMapperExtExports.h" #include "mitkCommon.h" #include "vtkVersionMacros.h" #include "vtkVolumeMapper.h" -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) - class vtkVolumeProperty; class vtkRenderWindow; // class vtkKWAMRVolumeMapper; // friend class. class MITKMAPPEREXT_EXPORT vtkMitkGPUVolumeRayCastMapper : public vtkVolumeMapper { public: vtkTypeMacro(vtkMitkGPUVolumeRayCastMapper, vtkVolumeMapper); void PrintSelf(ostream &os, vtkIndent indent) override; // Description: // If AutoAdjustSampleDistances is on, the the ImageSampleDistance // will be varied to achieve the allocated render time of this // prop (controlled by the desired update rate and any culling in // use). vtkSetClampMacro(AutoAdjustSampleDistances, int, 0, 1); vtkGetMacro(AutoAdjustSampleDistances, int); vtkBooleanMacro(AutoAdjustSampleDistances, int); // Description: // Set/Get the distance between samples used for rendering // when AutoAdjustSampleDistances is off, or when this mapper // has more than 1 second allocated to it for rendering. // Initial value is 1.0. vtkSetMacro(SampleDistance, float); vtkGetMacro(SampleDistance, float); // Description: // Sampling distance in the XY image dimensions. Default value of 1 meaning // 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If // set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. This value // will be adjusted to meet a desired frame rate when AutoAdjustSampleDistances // is on. vtkSetClampMacro(ImageSampleDistance, float, 0.1f, 100.0f); vtkGetMacro(ImageSampleDistance, float); // Description: // This is the minimum image sample distance allow when the image // sample distance is being automatically adjusted. vtkSetClampMacro(MinimumImageSampleDistance, float, 0.1f, 100.0f); vtkGetMacro(MinimumImageSampleDistance, float); // Description: // This is the maximum image sample distance allow when the image // sample distance is being automatically adjusted. vtkSetClampMacro(MaximumImageSampleDistance, float, 0.1f, 100.0f); vtkGetMacro(MaximumImageSampleDistance, float); // Description: // Set/Get the window / level applied to the final color. // This allows brightness / contrast adjustments on the // final image. // window is the width of the window. // level is the center of the window. // Initial window value is 1.0 // Initial level value is 0.5 // window cannot be null but can be negative, this way // values will be reversed. // |window| can be larger than 1.0 // level can be any real value. vtkSetMacro(FinalColorWindow, float); vtkGetMacro(FinalColorWindow, float); vtkSetMacro(FinalColorLevel, float); vtkGetMacro(FinalColorLevel, float); // Description: // Maximum size of the 3D texture in GPU memory. // Will default to the size computed from the graphics // card. Can be adjusted by the user. vtkSetMacro(MaxMemoryInBytes, vtkIdType); vtkGetMacro(MaxMemoryInBytes, vtkIdType); // Description: // Maximum fraction of the MaxMemoryInBytes that should // be used to hold the texture. Valid values are 0.1 to // 1.0. vtkSetClampMacro(MaxMemoryFraction, float, 0.1f, 1.0f); vtkGetMacro(MaxMemoryFraction, float); // Description: // Tells if the mapper will report intermediate progress. // Initial value is true. As the progress works with a GL blocking // call (glFinish()), this can be useful for huge dataset but can // slow down rendering of small dataset. It should be set to true // for big dataset or complex shading and streaming but to false for // small datasets. vtkSetMacro(ReportProgress, bool); vtkGetMacro(ReportProgress, bool); // Description: // Based on hardware and properties, we may or may not be able to // render using 3D texture mapping. This indicates if 3D texture // mapping is supported by the hardware, and if the other extensions // necessary to support the specific properties are available. virtual int IsRenderSupported(vtkRenderWindow *vtkNotUsed(window), vtkVolumeProperty *vtkNotUsed(property)) { return 0; } void CreateCanonicalView(vtkRenderer *ren, vtkVolume *volume, vtkImageData *image, int blend_mode, double viewDirection[3], double viewUp[3]); void SetMaskInput(vtkImageData *mask); vtkGetObjectMacro(MaskInput, vtkImageData); // Description: // Tells how much mask color transfer function is used compared to the // standard color transfer function when the mask is true. // 0.0 means only standard color transfer function. // 1.0 means only mask color tranfer function. // Initial value is 1.0. vtkSetClampMacro(MaskBlendFactor, float, 0.0f, 1.0f); vtkGetMacro(MaskBlendFactor, float); // BTX // Description: // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE // Initialize rendering for this volume. void Render(vtkRenderer *, vtkVolume *) override; // Description: // Handled in the subclass - the actual render method // \pre input is up-to-date. virtual void GPURender(vtkRenderer *, vtkVolume *) {} // Description: // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE // Release any graphics resources that are being consumed by this mapper. // The parameter window could be used to determine which graphic // resources to release. // \deprecatedSince{2013_12} DEPRECATED(void ReleaseGraphicsResources(vtkWindow *) override){}; // Description: // Return how much the dataset has to be reduced in each dimension to // fit on the GPU. If the value is 1.0, there is no need to reduce the // dataset. // \pre the calling thread has a current OpenGL context. // \pre mapper_supported: IsRenderSupported(renderer->GetRenderWindow(),0) // The computation is based on hardware limits (3D texture indexable size) // and MaxMemoryInBytes. // \post valid_i_ratio: ratio[0]>0 && ratio[0]<=1.0 // \post valid_j_ratio: ratio[1]>0 && ratio[1]<=1.0 // \post valid_k_ratio: ratio[2]>0 && ratio[2]<=1.0 virtual void GetReductionRatio(double ratio[3]) = 0; // ETX protected: vtkMitkGPUVolumeRayCastMapper(); ~vtkMitkGPUVolumeRayCastMapper(); // Check to see that the render will be OK int ValidateRender(vtkRenderer *, vtkVolume *); // Special version of render called during the creation // of a canonical view. void CanonicalViewRender(vtkRenderer *, vtkVolume *); // Methods called by the AMR Volume Mapper. virtual void PreRender(vtkRenderer *ren, vtkVolume *vol, double datasetBounds[6], double scalarRange[2], int numberOfScalarComponents, unsigned int numberOfLevels) = 0; // \pre input is up-to-date virtual void RenderBlock(vtkRenderer *ren, vtkVolume *vol, unsigned int level) = 0; virtual void PostRender(vtkRenderer *ren, int numberOfScalarComponents) = 0; // Description: // Called by the AMR Volume Mapper. // Set the flag that tells if the scalars are on point data (0) or // cell data (1). void SetCellFlag(int cellFlag); // The distance between sample points along the ray float SampleDistance; float ImageSampleDistance; float MinimumImageSampleDistance; float MaximumImageSampleDistance; int AutoAdjustSampleDistances; int SmallVolumeRender; double BigTimeToDraw; double SmallTimeToDraw; float FinalColorWindow; float FinalColorLevel; vtkIdType MaxMemoryInBytes; float MaxMemoryFraction; // 1 if we are generating the canonical image, 0 otherwise int GeneratingCanonicalView; vtkImageData *CanonicalViewImageData; // Description: // Set the mapper in AMR Mode or not. Initial value is false. // Called only by the vtkKWAMRVolumeMapper vtkSetClampMacro(AMRMode, int, 0, 1); vtkGetMacro(AMRMode, int); vtkBooleanMacro(AMRMode, int); int AMRMode; int CellFlag; // point data or cell data (or field data, not handled) ? // Description: // Compute the cropping planes clipped by the bounds of the volume. // The result is put into this->ClippedCroppingRegionPlanes. // NOTE: IT WILL BE MOVED UP TO vtkVolumeMapper after bullet proof usage // in this mapper. Other subclasses will use the ClippedCroppingRegionsPlanes // members instead of CroppingRegionPlanes. // \pre volume_exists: this->GetInput()!=0 // \pre valid_cropping: this->Cropping && // this->CroppingRegionPlanes[0]CroppingRegionPlanes[1] && // this->CroppingRegionPlanes[2]CroppingRegionPlanes[3] && // this->CroppingRegionPlanes[4]CroppingRegionPlanes[5]) virtual void ClipCroppingRegionPlanes(); double ClippedCroppingRegionPlanes[6]; bool ReportProgress; vtkImageData *MaskInput; float MaskBlendFactor; vtkGetObjectMacro(TransformedInput, vtkImageData); void SetTransformedInput(vtkImageData *); vtkImageData *TransformedInput; // Description: // This is needed only to check if the input data has been changed since the last // Render() call. vtkImageData *LastInput; private: vtkMitkGPUVolumeRayCastMapper(const vtkMitkGPUVolumeRayCastMapper &); // Not implemented. void operator=(const vtkMitkGPUVolumeRayCastMapper &); // Not implemented. }; #endif - -#endif diff --git a/Modules/MapperExt/include/vtkMitkOpenGLVolumeTextureMapper3D.h b/Modules/MapperExt/include/vtkMitkOpenGLVolumeTextureMapper3D.h deleted file mode 100644 index e06844a66f..0000000000 --- a/Modules/MapperExt/include/vtkMitkOpenGLVolumeTextureMapper3D.h +++ /dev/null @@ -1,148 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - -// .NAME vtkMitkOpenGLVolumeTextureMapper3D - concrete implementation of 3D volume texture mapping - -// .SECTION Description -// vtkMitkOpenGLVolumeTextureMapper3D renders a volume using 3D texture mapping. -// See vtkMitkVolumeTextureMapper3D for full description. - -// .SECTION see also -// vtkMitkVolumeTextureMapper3D vtkVolumeMapper - -#ifndef __vtkMitkOpenGLVolumeTextureMapper3D_h -#define __vtkMitkOpenGLVolumeTextureMapper3D_h - -#include "MitkMapperExtExports.h" -#include "mitkBaseRenderer.h" -#include "vtkMitkVolumeTextureMapper3D.h" - -#ifndef VTK_IMPLEMENT_MESA_CXX -#include "vtkOpenGL.h" // GLfloat type is used in some method signatures. -#endif - -class vtkRenderWindow; -class vtkVolumeProperty; - -#include "mitkCommon.h" - -class MITKMAPPEREXT_EXPORT vtkMitkOpenGLVolumeTextureMapper3D : public vtkMitkVolumeTextureMapper3D -{ -public: - vtkTypeMacro(vtkMitkOpenGLVolumeTextureMapper3D, vtkMitkVolumeTextureMapper3D); - void PrintSelf(ostream &os, vtkIndent indent) override; - - static vtkMitkOpenGLVolumeTextureMapper3D *New(); - - // Description: - // Is hardware rendering supported? No if the input data is - // more than one independent component, or if the hardware does - // not support the required extensions - // int IsRenderSupported(vtkVolumeProperty *); - int IsRenderSupported(vtkRenderer *ren, vtkVolumeProperty *) override; - - // BTX - - // Description: - // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE - // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS - // Render the volume - virtual void Render(vtkRenderer *ren, vtkVolume *vol) override; - - // ETX - - // Desciption: - // Initialize when we go to render, or go to answer the - // IsRenderSupported question. Don't call unless we have - // a valid OpenGL context! - vtkGetMacro(Initialized, int); - - // Description: - // Release any graphics resources that are being consumed by this texture. - // The parameter window could be used to determine which graphic - // resources to release. - // deprecatedSince{2013_12} Use ReleaseGraphicsResources(mitk::BaseRenderer* renderer) instead - DEPRECATED(void ReleaseGraphicsResources(vtkWindow *) override); - - // Description: - // Release any graphics resources that are being consumed by this texture. - // The parameter renderer could be used to determine which graphic - // resources to release. - void ReleaseGraphicsResources(mitk::BaseRenderer *renderer); - -protected: - vtkMitkOpenGLVolumeTextureMapper3D(); - ~vtkMitkOpenGLVolumeTextureMapper3D(); - - bool RenderPossible; - - // BTX - - void GetLightInformation(vtkRenderer *ren, - vtkVolume *vol, - GLfloat lightDirection[2][4], - GLfloat lightDiffuseColor[2][4], - GLfloat lightSpecularColor[2][4], - GLfloat halfwayVector[2][4], - GLfloat *ambient); - // ETX - - int Initialized; - GLuint Volume1Index; - GLuint Volume2Index; - GLuint Volume3Index; - GLuint ColorLookupIndex; - GLuint AlphaLookupIndex; - - GLuint prgOneComponentShade; - GLuint prgRGBAShade; - - vtkRenderWindow *RenderWindow; - - bool SupportsCompressedTexture; - - // void Initialize(); - void Initialize(vtkRenderer *r); - - virtual void RenderFP(vtkRenderer *ren, vtkVolume *vol); - - void SetupOneIndependentTextures(vtkRenderer *ren, vtkVolume *vol); - void RenderOneIndependentShadeFP(vtkRenderer *ren, vtkVolume *vol); - - void SetupRGBATextures(vtkRenderer *ren, vtkVolume *vol); - void RenderRGBAShadeFP(vtkRenderer *ren, vtkVolume *vol); - - void DeleteTextureIndex(GLuint *index); - void CreateTextureIndex(GLuint *index); - - void RenderPolygons(vtkRenderer *ren, vtkVolume *vol, int stages[4]); - - void SetupProgramLocalsForShadingFP(vtkRenderer *ren, vtkVolume *vol); - - void Setup3DTextureParameters(bool linear); - - void ComputeVolumeDimensions(); - - bool UpdateVolumes(vtkVolume *); - - bool UpdateVolumesRGBA(vtkVolume *); - -private: - vtkMitkOpenGLVolumeTextureMapper3D(const vtkMitkOpenGLVolumeTextureMapper3D &); // Not implemented. - void operator=(const vtkMitkOpenGLVolumeTextureMapper3D &); // Not implemented. -}; - -#endif diff --git a/Modules/MapperExt/include/vtkMitkVolumeTextureMapper3D.h b/Modules/MapperExt/include/vtkMitkVolumeTextureMapper3D.h deleted file mode 100644 index 7fe2ded61a..0000000000 --- a/Modules/MapperExt/include/vtkMitkVolumeTextureMapper3D.h +++ /dev/null @@ -1,223 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - -// .NAME vtkMitkVolumeTextureMapper3D - volume render with 3D texture mapping - -// .SECTION Description -// vtkMitkVolumeTextureMapper3D renders a volume using 3D texture mapping. -// This class is actually an abstract superclass - with all the actual -// work done by vtkMitkOpenGLVolumeTextureMapper3D. -// -// This mappers currently supports: -// -// - any data type as input -// - one component, or two or four non-independent components -// - composite blending -// - intermixed opaque geometry -// - multiple volumes can be rendered if they can -// be sorted into back-to-front order (use the vtkFrustumCoverageCuller) -// -// This mapper does not support: -// - more than one independent component -// - maximum intensity projection -// -// Internally, this mapper will potentially change the resolution of the -// input data. The data will be resampled to be a power of two in each -// direction, and also no greater than 128*256*256 voxels (any aspect) -// for one or two component data, or 128*128*256 voxels (any aspect) -// for four component data. The limits are currently hardcoded after -// a check using the GL_PROXY_TEXTURE3D because some graphics drivers -// were always responding "yes" to the proxy call despite not being -// able to allocate that much texture memory. -// -// Currently, calculations are computed using 8 bits per RGBA channel. -// In the future this should be expanded to handle newer boards that -// can support 15 bit float compositing. -// -// This mapper supports two main families of graphics hardware: -// nvidia and ATI. There are two different implementations of -// 3D texture mapping used - one based on nvidia's GL_NV_texture_shader2 -// and GL_NV_register_combiners2 extension, and one based on -// ATI's GL_ATI_fragment_shader (supported also by some nvidia boards) -// To use this class in an application that will run on various -// hardware configurations, you should have a back-up volume rendering -// method. You should create a vtkMitkVolumeTextureMapper3D, assign its -// input, make sure you have a current OpenGL context (you've rendered -// at least once), then call IsRenderSupported with a vtkVolumeProperty -// as an argument. This method will return 0 if the input has more than -// one independent component, or if the graphics hardware does not -// support the set of required extensions for using at least one of -// the two implemented methods (nvidia or ati) -// -// .SECTION Thanks -// Thanks to Alexandre Gouaillard at the Megason Lab, Department of Systems -// Biology, Harvard Medical School -// https://wiki.med.harvard.edu/SysBio/Megason/ -// for the idea and initial patch to speed-up rendering with compressed -// textures. -// -// .SECTION see also -// vtkVolumeMapper - -#ifndef __vtkMitkVolumeTextureMapper3D_h -#define __vtkMitkVolumeTextureMapper3D_h - -#include "MitkMapperExtExports.h" -#include "vtkVolumeMapper.h" - -class vtkImageData; -class vtkColorTransferFunction; -class vtkPiecewiseFunction; -class vtkVolumeProperty; - -#include "mitkCommon.h" - -class MITKMAPPEREXT_EXPORT vtkMitkVolumeTextureMapper3D : public vtkVolumeMapper -{ -public: - vtkTypeMacro(vtkMitkVolumeTextureMapper3D, vtkVolumeMapper); - void PrintSelf(ostream &os, vtkIndent indent) override; - - // static vtkMitkVolumeTextureMapper3D *New(); //VTK6_TODO - - // Description: - // The distance at which to space sampling planes. This - // may not be honored for interactive renders. An interactive - // render is defined as one that has less than 1 second of - // allocated render time. - vtkSetMacro(SampleDistance, float); - vtkGetMacro(SampleDistance, float); - - // Description: - // These are the dimensions of the 3D texture - vtkGetVectorMacro(VolumeDimensions, int, 3); - - // Description: - // This is the spacing of the 3D texture - vtkGetVectorMacro(VolumeSpacing, float, 3); - - // Description: - // Based on hardware and properties, we may or may not be able to - // render using 3D texture mapping. This indicates if 3D texture - // mapping is supported by the hardware, and if the other extensions - // necessary to support the specific properties are available. - virtual int IsRenderSupported(vtkRenderer *, vtkVolumeProperty *) = 0; - - // Description: - // Allow access to the number of polygons used for the - // rendering. - vtkGetMacro(NumberOfPolygons, int); - - // Description: - // Allow access to the actual sample distance used to render - // the image. - vtkGetMacro(ActualSampleDistance, float); - - // BTX - - // Description: - // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE - // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS - // Render the volume - virtual void Render(vtkRenderer *, vtkVolume *) override{}; - - // Description: - // Set/Get if the mapper use compressed textures (if supported by the - // hardware). Initial value is false. - // There are two reasons to use compressed textures: 1. rendering can be 4 - // times faster. 2. It saves some VRAM. - // There is one reason to not use compressed textures: quality may be lower - // than with uncompressed textures. - vtkSetMacro(UseCompressedTexture, bool); - vtkGetMacro(UseCompressedTexture, bool); - - void UpdateMTime(); - -protected: - vtkMitkVolumeTextureMapper3D(); - ~vtkMitkVolumeTextureMapper3D(); - - float *PolygonBuffer; - float *IntersectionBuffer; - int NumberOfPolygons; - int BufferSize; - - /* - unsigned char *Volume1; - unsigned char *Volume2; - unsigned char *Volume3; - */ - /* - int VolumeSize; - int VolumeComponents; - */ - - int VolumeDimensions[3]; - float VolumeSpacing[3]; - - float SampleDistance; - float ActualSampleDistance; - - vtkImageData *SavedTextureInput; - vtkImageData *SavedParametersInput; - - vtkColorTransferFunction *SavedRGBFunction; - vtkPiecewiseFunction *SavedGrayFunction; - vtkPiecewiseFunction *SavedScalarOpacityFunction; - vtkPiecewiseFunction *SavedGradientOpacityFunction; - int SavedColorChannels; - float SavedSampleDistance; - float SavedScalarOpacityDistance; - - unsigned char ColorLookup[65536 * 4]; - unsigned char AlphaLookup[65536]; - float TempArray1[3 * 4096]; - float TempArray2[4096]; - int ColorTableSize; - float ColorTableScale; - float ColorTableOffset; - - unsigned char DiffuseLookup[65536 * 4]; - unsigned char SpecularLookup[65536 * 4]; - - vtkTimeStamp SavedTextureMTime; - vtkTimeStamp SavedParametersMTime; - - bool UseCompressedTexture; - - bool SupportsNonPowerOfTwoTextures; - - // Description: - // For the given viewing direction, compute the set of polygons. - void ComputePolygons(vtkRenderer *ren, vtkVolume *vol, double bounds[6]); - - // Description: - // Update the internal RGBA representation of the volume. Return 1 if - // anything change, 0 if nothing changed. - int UpdateColorLookup(vtkVolume *); - - // Description: - // Impemented in subclass - check is texture size is OK. - // BTX - virtual int IsTextureSizeSupported(int vtkNotUsed(size)[3], int vtkNotUsed(components)) { return 0; } - // ETX - -private: - vtkMitkVolumeTextureMapper3D(const vtkMitkVolumeTextureMapper3D &); // Not implemented. - void operator=(const vtkMitkVolumeTextureMapper3D &); // Not implemented. -}; - -#endif diff --git a/Modules/MapperExt/include/vtkUnstructuredGridMapper.h b/Modules/MapperExt/include/vtkUnstructuredGridMapper.h index adf3eff216..12344b922b 100644 --- a/Modules/MapperExt/include/vtkUnstructuredGridMapper.h +++ b/Modules/MapperExt/include/vtkUnstructuredGridMapper.h @@ -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. ===================================================================*/ #ifndef __vtkUnstructuredGridMapper_h #define __vtkUnstructuredGridMapper_h #include "MitkMapperExtExports.h" #include "mitkBaseRenderer.h" #include "mitkBoundingObject.h" #include "mitkCommon.h" #include "vtkMapper.h" class vtkPolyDataMapper; class vtkGeometryFilter; class vtkUnstructuredGrid; class MITKMAPPEREXT_EXPORT vtkUnstructuredGridMapper : public vtkMapper { public: static vtkUnstructuredGridMapper *New(); vtkTypeMacro(vtkUnstructuredGridMapper, vtkMapper); void PrintSelf(ostream &os, vtkIndent indent) override; void Render(vtkRenderer *ren, vtkActor *act) override; // Description: // Get the internal poly data mapper used to map data set to graphics system. vtkGetObjectMacro(PolyDataMapper, vtkPolyDataMapper); // Description: // Release any graphics resources that are being consumed by this mapper. // The parameter window could be used to determine which graphic // resources to release. // deprecatedSince{2013_12} Use ReleaseGraphicsResources(mitk::BaseRenderer* renderer) instead DEPRECATED(void ReleaseGraphicsResources(vtkWindow *) override); // Description: // Release any graphics resources that are being consumed by this mapper. // The parameter renderer could be used to determine which graphic // resources to release. // deprecatedSince{2013_12} Use ReleaseGraphicsResources(mitk::BaseRenderer* renderer) instead void ReleaseGraphicsResources(mitk::BaseRenderer *renderer); // Description: // Get the mtime also considering the lookup table. - unsigned long GetMTime() override; + vtkMTimeType GetMTime() override; // Description: // Set the Input of this mapper. void SetInput(vtkUnstructuredGrid *input); vtkUnstructuredGrid *GetInput(); void SetBoundingObject(mitk::BoundingObject *bo); protected: vtkUnstructuredGridMapper(); ~vtkUnstructuredGridMapper(); vtkGeometryFilter *GeometryExtractor; vtkPolyDataMapper *PolyDataMapper; mitk::BoundingObject::Pointer m_BoundingObject; virtual void ReportReferences(vtkGarbageCollector *) override; // see algorithm for more info virtual int FillInputPortInformation(int port, vtkInformation *info) override; private: vtkUnstructuredGridMapper(const vtkUnstructuredGridMapper &); // Not implemented. void operator=(const vtkUnstructuredGridMapper &); // Not implemented. }; #endif // __vtkUnstructuredGridMapper_h diff --git a/Modules/MapperExt/src/mitkGPUVolumeMapper3D.cpp b/Modules/MapperExt/src/mitkGPUVolumeMapper3D.cpp index 4db7aa4cf1..d8c81045f7 100644 --- a/Modules/MapperExt/src/mitkGPUVolumeMapper3D.cpp +++ b/Modules/MapperExt/src/mitkGPUVolumeMapper3D.cpp @@ -1,708 +1,592 @@ /*=================================================================== 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 GPU_INFO MITK_INFO("mapper.vr") #define GPU_WARN MITK_WARN("mapper.vr") #define GPU_ERROR MITK_ERROR("mapper.vr") -#include -VTK_MODULE_INIT(vtkRenderingVolumeOpenGL); - #include "mitkGPUVolumeMapper3D.h" #include "mitkDataNode.h" #include "mitkColorProperty.h" #include "mitkColorProperty.h" #include "mitkLevelWindow.h" #include "mitkLevelWindowProperty.h" #include "mitkLookupTableProperty.h" #include "mitkProperties.h" #include "mitkRenderingManager.h" #include "mitkTransferFunctionInitializer.h" #include "mitkTransferFunctionProperty.h" #include "mitkVtkPropRenderer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include #include #include -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) - #include "vtkMitkGPUVolumeRayCastMapper.h" -#endif - -#include "vtkMitkOpenGLVolumeTextureMapper3D.h" #include "vtkOpenGLGPUVolumeRayCastMapper.h" const mitk::Image *mitk::GPUVolumeMapper3D::GetInput() { return static_cast(GetDataNode()->GetData()); } void mitk::GPUVolumeMapper3D::MitkRenderVolumetricGeometry(mitk::BaseRenderer *renderer) { - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - VtkMapper::MitkRenderVolumetricGeometry(renderer); - if (ls->m_gpuInitialized) - ls->m_MapperGPU->UpdateMTime(); + // if(ls->m_gpuInitialized) + // ls->m_MapperGPU->UpdateMTime(); } -bool mitk::GPUVolumeMapper3D::InitGPU(mitk::BaseRenderer *renderer) +bool mitk::GPUVolumeMapper3D::InitGPU(mitk::BaseRenderer * /*renderer*/) { - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - if (ls->m_gpuInitialized) - return ls->m_gpuSupported; - - ls->m_VtkRenderWindow = renderer->GetVtkRenderer()->GetRenderWindow(); - - GPU_INFO << "initializing gpu-slicing-vr (vtkMitkOpenGLVolumeTextureMapper3D)"; - - ls->m_MapperGPU = vtkSmartPointer::New(); - ls->m_MapperGPU->SetUseCompressedTexture(false); - ls->m_MapperGPU->SetSampleDistance(1.0); - - ls->m_VolumePropertyGPU = vtkSmartPointer::New(); - ls->m_VolumePropertyGPU->ShadeOn(); - ls->m_VolumePropertyGPU->SetAmbient(0.25f); // 0.05f - ls->m_VolumePropertyGPU->SetDiffuse(0.50f); // 0.45f - ls->m_VolumePropertyGPU->SetSpecular(0.40f); // 0.50f - ls->m_VolumePropertyGPU->SetSpecularPower(16.0f); - ls->m_VolumePropertyGPU->SetInterpolationTypeToLinear(); - - ls->m_VolumeGPU = vtkSmartPointer::New(); - ls->m_VolumeGPU->SetMapper(ls->m_MapperGPU); - ls->m_VolumeGPU->SetProperty(ls->m_VolumePropertyGPU); - ls->m_VolumeGPU->VisibilityOn(); - - ls->m_MapperGPU->SetInputConnection(this->m_UnitSpacingImageFilter->GetOutputPort()); - - ls->m_gpuSupported = ls->m_MapperGPU->IsRenderSupported(renderer->GetVtkRenderer(), ls->m_VolumePropertyGPU); - - ls->m_gpuInitialized = true; - - return ls->m_gpuSupported; + return false; // TODO 18922 } void mitk::GPUVolumeMapper3D::InitCPU(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (ls->m_cpuInitialized) return; ls->m_VtkRenderWindow = renderer->GetVtkRenderer()->GetRenderWindow(); ls->m_MapperCPU = vtkSmartPointer::New(); int numThreads = ls->m_MapperCPU->GetNumberOfThreads(); GPU_INFO << "initializing cpu-raycast-vr (vtkFixedPointVolumeRayCastMapper) (" << numThreads << " threads)"; ls->m_MapperCPU->SetSampleDistance(1.0); // ls->m_MapperCPU->LockSampleDistanceToInputSpacingOn(); ls->m_MapperCPU->SetImageSampleDistance(1.0); ls->m_MapperCPU->IntermixIntersectingGeometryOn(); ls->m_MapperCPU->SetAutoAdjustSampleDistances(0); ls->m_VolumePropertyCPU = vtkSmartPointer::New(); ls->m_VolumePropertyCPU->ShadeOn(); ls->m_VolumePropertyCPU->SetAmbient(0.10f); // 0.05f ls->m_VolumePropertyCPU->SetDiffuse(0.50f); // 0.45f ls->m_VolumePropertyCPU->SetSpecular(0.40f); // 0.50f ls->m_VolumePropertyCPU->SetSpecularPower(16.0f); ls->m_VolumePropertyCPU->SetInterpolationTypeToLinear(); ls->m_VolumeCPU = vtkSmartPointer::New(); ls->m_VolumeCPU->SetMapper(ls->m_MapperCPU); ls->m_VolumeCPU->SetProperty(ls->m_VolumePropertyCPU); ls->m_VolumeCPU->VisibilityOn(); ls->m_MapperCPU->SetInputConnection(m_UnitSpacingImageFilter->GetOutputPort()); // m_Resampler->GetOutput()); ls->m_cpuInitialized = true; } -void mitk::GPUVolumeMapper3D::DeinitGPU(mitk::BaseRenderer *renderer) -{ - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - if (ls->m_gpuInitialized) - { - GPU_INFO << "deinitializing gpu-slicing-vr"; - // deinit renderwindow, this is needed to release the memory allocated on the gpu - // to prevent leaking memory on the gpu - ls->m_MapperGPU->ReleaseGraphicsResources(renderer->GetVtkRenderer()->GetVTKWindow()); - ls->m_VolumePropertyGPU = nullptr; - ls->m_MapperGPU = nullptr; - ls->m_VolumeGPU = nullptr; - ls->m_gpuInitialized = false; - } -} - void mitk::GPUVolumeMapper3D::DeinitCPU(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (!ls->m_cpuInitialized) return; GPU_INFO << "deinitializing cpu-raycast-vr"; ls->m_VolumePropertyCPU = nullptr; ls->m_MapperCPU = nullptr; ls->m_VolumeCPU = nullptr; ls->m_cpuInitialized = false; } mitk::GPUVolumeMapper3D::GPUVolumeMapper3D() { m_Volumenullptr = 0; m_commonInitialized = false; } mitk::GPUVolumeMapper3D::~GPUVolumeMapper3D() { DeinitCommon(); } void mitk::GPUVolumeMapper3D::InitCommon() { if (m_commonInitialized) return; m_UnitSpacingImageFilter = vtkSmartPointer::New(); m_UnitSpacingImageFilter->SetOutputSpacing(1.0, 1.0, 1.0); CreateDefaultTransferFunctions(); m_commonInitialized = true; } void mitk::GPUVolumeMapper3D::DeinitCommon() { if (!m_commonInitialized) return; m_commonInitialized = false; } bool mitk::GPUVolumeMapper3D::IsRenderable(mitk::BaseRenderer *renderer) { if (!GetDataNode()) return false; DataNode *node = GetDataNode(); bool visible = true; node->GetVisibility(visible, renderer, "visible"); if (!visible) return false; bool value = false; if (!node->GetBoolProperty("volumerendering", value, renderer)) return false; if (!value) return false; mitk::Image *input = const_cast(this->GetInput()); if (!input || !input->IsInitialized()) return false; vtkImageData *inputData = input->GetVtkImageData(this->GetTimestep()); if (inputData == nullptr) return false; return true; } void mitk::GPUVolumeMapper3D::InitVtkMapper(mitk::BaseRenderer *renderer) { -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) if (IsRAYEnabled(renderer)) { DeinitCPU(renderer); - DeinitGPU(renderer); if (!InitRAY(renderer)) { GPU_WARN << "hardware renderer can't initialize ... falling back to software renderer"; goto fallback; } } - else -#endif - if (IsGPUEnabled(renderer)) + else if (IsGPUEnabled(renderer)) { DeinitCPU(renderer); -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) DeinitRAY(renderer); -#endif if (!InitGPU(renderer)) { GPU_WARN << "hardware renderer can't initialize ... falling back to software renderer"; goto fallback; } } else { fallback: - DeinitGPU(renderer); -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) DeinitRAY(renderer); -#endif InitCPU(renderer); } } vtkProp *mitk::GPUVolumeMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { if (!IsRenderable(renderer)) { if (!m_Volumenullptr) { m_Volumenullptr = vtkSmartPointer::New(); m_Volumenullptr->VisibilityOff(); } return m_Volumenullptr; } InitCommon(); InitVtkMapper(renderer); LocalStorage *ls = m_LSH.GetLocalStorage(renderer); -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) if (ls->m_rayInitialized) return ls->m_VolumeRAY; -#endif if (ls->m_gpuInitialized) return ls->m_VolumeGPU; return ls->m_VolumeCPU; } void mitk::GPUVolumeMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { if (!IsRenderable(renderer)) return; InitCommon(); InitVtkMapper(renderer); mitk::Image *input = const_cast(this->GetInput()); vtkImageData *inputData = input->GetVtkImageData(this->GetTimestep()); m_UnitSpacingImageFilter->SetInputData(inputData); LocalStorage *ls = m_LSH.GetLocalStorage(renderer); -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) if (ls->m_rayInitialized) { GenerateDataRAY(renderer); } else -#endif if (ls->m_gpuInitialized) { GenerateDataGPU(renderer); } else { GenerateDataCPU(renderer); } // UpdateTransferFunctions UpdateTransferFunctions(renderer); } -void mitk::GPUVolumeMapper3D::GenerateDataGPU(mitk::BaseRenderer *renderer) +void mitk::GPUVolumeMapper3D::GenerateDataGPU(mitk::BaseRenderer * /*renderer*/) { - LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - - bool useCompression = false; - GetDataNode()->GetBoolProperty("volumerendering.gpu.usetexturecompression", useCompression, renderer); - ls->m_MapperGPU->SetUseCompressedTexture(useCompression); - - if (IsLODEnabled(renderer) && mitk::RenderingManager::GetInstance()->GetNextLOD(renderer) == 0) - ls->m_MapperGPU->SetSampleDistance(2.0); - else - ls->m_MapperGPU->SetSampleDistance(1.0); - - // Updating shadings - { - float value = 0; - if (GetDataNode()->GetFloatProperty("volumerendering.gpu.ambient", value, renderer)) - ls->m_VolumePropertyGPU->SetAmbient(value); - if (GetDataNode()->GetFloatProperty("volumerendering.gpu.diffuse", value, renderer)) - ls->m_VolumePropertyGPU->SetDiffuse(value); - if (GetDataNode()->GetFloatProperty("volumerendering.gpu.specular", value, renderer)) - ls->m_VolumePropertyGPU->SetSpecular(value); - if (GetDataNode()->GetFloatProperty("volumerendering.gpu.specular.power", value, renderer)) - ls->m_VolumePropertyGPU->SetSpecularPower(value); - } } void mitk::GPUVolumeMapper3D::GenerateDataCPU(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); int nextLod = mitk::RenderingManager::GetInstance()->GetNextLOD(renderer); if (IsLODEnabled(renderer) && nextLod == 0) { ls->m_MapperCPU->SetImageSampleDistance(3.5); ls->m_MapperCPU->SetSampleDistance(1.25); ls->m_VolumePropertyCPU->SetInterpolationTypeToNearest(); } else { ls->m_MapperCPU->SetImageSampleDistance(1.0); ls->m_MapperCPU->SetSampleDistance(1.0); ls->m_VolumePropertyCPU->SetInterpolationTypeToLinear(); } // Check raycasting mode if (IsMIPEnabled(renderer)) ls->m_MapperCPU->SetBlendModeToMaximumIntensity(); else ls->m_MapperCPU->SetBlendModeToComposite(); // Updating shadings { float value = 0; if (GetDataNode()->GetFloatProperty("volumerendering.cpu.ambient", value, renderer)) ls->m_VolumePropertyCPU->SetAmbient(value); if (GetDataNode()->GetFloatProperty("volumerendering.cpu.diffuse", value, renderer)) ls->m_VolumePropertyCPU->SetDiffuse(value); if (GetDataNode()->GetFloatProperty("volumerendering.cpu.specular", value, renderer)) ls->m_VolumePropertyCPU->SetSpecular(value); if (GetDataNode()->GetFloatProperty("volumerendering.cpu.specular.power", value, renderer)) ls->m_VolumePropertyCPU->SetSpecularPower(value); } } void mitk::GPUVolumeMapper3D::CreateDefaultTransferFunctions() { m_DefaultOpacityTransferFunction = vtkSmartPointer::New(); m_DefaultOpacityTransferFunction->AddPoint(0.0, 0.0); m_DefaultOpacityTransferFunction->AddPoint(255.0, 0.8); m_DefaultOpacityTransferFunction->ClampingOn(); m_DefaultGradientTransferFunction = vtkSmartPointer::New(); m_DefaultGradientTransferFunction->AddPoint(0.0, 0.0); m_DefaultGradientTransferFunction->AddPoint(255.0, 0.8); m_DefaultGradientTransferFunction->ClampingOn(); m_DefaultColorTransferFunction = vtkSmartPointer::New(); m_DefaultColorTransferFunction->AddRGBPoint(0.0, 0.0, 0.0, 0.0); m_DefaultColorTransferFunction->AddRGBPoint(127.5, 1, 1, 0.0); m_DefaultColorTransferFunction->AddRGBPoint(255.0, 0.8, 0.2, 0); m_DefaultColorTransferFunction->ClampingOn(); m_BinaryOpacityTransferFunction = vtkSmartPointer::New(); m_BinaryOpacityTransferFunction->AddPoint(0, 0.0); m_BinaryOpacityTransferFunction->AddPoint(1, 1.0); m_BinaryGradientTransferFunction = vtkSmartPointer::New(); m_BinaryGradientTransferFunction->AddPoint(0.0, 1.0); m_BinaryColorTransferFunction = vtkSmartPointer::New(); } void mitk::GPUVolumeMapper3D::UpdateTransferFunctions(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); vtkPiecewiseFunction *opacityTransferFunction = m_DefaultOpacityTransferFunction; vtkPiecewiseFunction *gradientTransferFunction = m_DefaultGradientTransferFunction; vtkColorTransferFunction *colorTransferFunction = m_DefaultColorTransferFunction; bool isBinary = false; GetDataNode()->GetBoolProperty("binary", isBinary, renderer); if (isBinary) { opacityTransferFunction = m_BinaryOpacityTransferFunction; gradientTransferFunction = m_BinaryGradientTransferFunction; colorTransferFunction = m_BinaryColorTransferFunction; colorTransferFunction->RemoveAllPoints(); float rgb[3]; if (!GetDataNode()->GetColor(rgb, renderer)) rgb[0] = rgb[1] = rgb[2] = 1; colorTransferFunction->AddRGBPoint(0, rgb[0], rgb[1], rgb[2]); colorTransferFunction->Modified(); } else { mitk::TransferFunctionProperty *transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("TransferFunction", renderer)); if (transferFunctionProp) { opacityTransferFunction = transferFunctionProp->GetValue()->GetScalarOpacityFunction(); gradientTransferFunction = transferFunctionProp->GetValue()->GetGradientOpacityFunction(); colorTransferFunction = transferFunctionProp->GetValue()->GetColorTransferFunction(); } } if (ls->m_gpuInitialized) { ls->m_VolumePropertyGPU->SetColor(colorTransferFunction); ls->m_VolumePropertyGPU->SetScalarOpacity(opacityTransferFunction); ls->m_VolumePropertyGPU->SetGradientOpacity(gradientTransferFunction); } -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) - if (ls->m_rayInitialized) { ls->m_VolumePropertyRAY->SetColor(colorTransferFunction); ls->m_VolumePropertyRAY->SetScalarOpacity(opacityTransferFunction); ls->m_VolumePropertyRAY->SetGradientOpacity(gradientTransferFunction); } -#endif - if (ls->m_cpuInitialized) { ls->m_VolumePropertyCPU->SetColor(colorTransferFunction); ls->m_VolumePropertyCPU->SetScalarOpacity(opacityTransferFunction); ls->m_VolumePropertyCPU->SetGradientOpacity(gradientTransferFunction); } } void mitk::GPUVolumeMapper3D::ApplyProperties(vtkActor * /*actor*/, mitk::BaseRenderer * /*renderer*/) { // GPU_INFO << "ApplyProperties"; } void mitk::GPUVolumeMapper3D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) { // GPU_INFO << "SetDefaultProperties"; node->AddProperty("volumerendering", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.usemip", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.uselod", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.cpu.ambient", mitk::FloatProperty::New(0.10f), renderer, overwrite); node->AddProperty("volumerendering.cpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); node->AddProperty("volumerendering.cpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); node->AddProperty("volumerendering.cpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); bool usegpu = true; #ifdef __APPLE__ usegpu = false; node->AddProperty("volumerendering.uselod", mitk::BoolProperty::New(true), renderer, overwrite); #endif node->AddProperty("volumerendering.usegpu", mitk::BoolProperty::New(usegpu), renderer, overwrite); -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) - node->AddProperty("volumerendering.useray", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.ray.ambient", mitk::FloatProperty::New(0.25f), renderer, overwrite); node->AddProperty("volumerendering.ray.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); node->AddProperty("volumerendering.ray.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); node->AddProperty("volumerendering.ray.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); -#endif node->AddProperty("volumerendering.gpu.ambient", mitk::FloatProperty::New(0.25f), renderer, overwrite); node->AddProperty("volumerendering.gpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); node->AddProperty("volumerendering.gpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); node->AddProperty("volumerendering.gpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); node->AddProperty("volumerendering.gpu.usetexturecompression", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.gpu.reducesliceartifacts", mitk::BoolProperty::New(false), renderer, overwrite); node->AddProperty("binary", mitk::BoolProperty::New(false), renderer, overwrite); mitk::Image::Pointer image = dynamic_cast(node->GetData()); if (image.IsNotNull() && image->IsInitialized()) { if ((overwrite) || (node->GetProperty("levelwindow", renderer) == nullptr)) { mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); mitk::LevelWindow levelwindow; levelwindow.SetAuto(image); levWinProp->SetLevelWindow(levelwindow); node->SetProperty("levelwindow", levWinProp, renderer); } if ((overwrite) || (node->GetProperty("TransferFunction", renderer) == nullptr)) { // add a default transfer function mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(tf); tfInit->SetTransferFunctionMode(0); node->SetProperty("TransferFunction", mitk::TransferFunctionProperty::New(tf.GetPointer())); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } bool mitk::GPUVolumeMapper3D::IsLODEnabled(mitk::BaseRenderer *renderer) const { bool value = false; return GetDataNode()->GetBoolProperty("volumerendering.uselod", value, renderer) && value; } bool mitk::GPUVolumeMapper3D::IsMIPEnabled(mitk::BaseRenderer *renderer) { bool value = false; return GetDataNode()->GetBoolProperty("volumerendering.usemip", value, renderer) && value; } bool mitk::GPUVolumeMapper3D::IsGPUEnabled(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool value = false; return ls->m_gpuSupported && GetDataNode()->GetBoolProperty("volumerendering.usegpu", value, renderer) && value; } -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) - bool mitk::GPUVolumeMapper3D::InitRAY(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (ls->m_rayInitialized) return ls->m_raySupported; ls->m_VtkRenderWindow = renderer->GetVtkRenderer()->GetRenderWindow(); GPU_INFO << "initializing gpu-raycast-vr (vtkOpenGLGPUVolumeRayCastMapper)"; ls->m_MapperRAY = vtkSmartPointer::New(); ls->m_MapperRAY->SetAutoAdjustSampleDistances(0); ls->m_MapperRAY->SetSampleDistance(1.0); ls->m_VolumePropertyRAY = vtkSmartPointer::New(); ls->m_VolumePropertyRAY->ShadeOn(); ls->m_VolumePropertyRAY->SetAmbient(0.25f); // 0.05f ls->m_VolumePropertyRAY->SetDiffuse(0.50f); // 0.45f ls->m_VolumePropertyRAY->SetSpecular(0.40f); // 0.50f ls->m_VolumePropertyRAY->SetSpecularPower(16.0f); ls->m_VolumePropertyRAY->SetInterpolationTypeToLinear(); ls->m_VolumeRAY = vtkSmartPointer::New(); ls->m_VolumeRAY->SetMapper(ls->m_MapperRAY); ls->m_VolumeRAY->SetProperty(ls->m_VolumePropertyRAY); ls->m_VolumeRAY->VisibilityOn(); ls->m_MapperRAY->SetInputConnection(this->m_UnitSpacingImageFilter->GetOutputPort()); ls->m_raySupported = ls->m_MapperRAY->IsRenderSupported(renderer->GetRenderWindow(), ls->m_VolumePropertyRAY); ls->m_rayInitialized = true; return ls->m_raySupported; } void mitk::GPUVolumeMapper3D::DeinitRAY(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (ls->m_rayInitialized) { GPU_INFO << "deinitializing gpu-raycast-vr"; ls->m_MapperRAY = nullptr; ls->m_VolumePropertyRAY = nullptr; // Here ReleaseGraphicsResources has to be called to avoid VTK error messages. // This seems like a VTK bug, because ReleaseGraphicsResources() is ment for internal use, // but you cannot just delete the object (last smartpointer reference) without getting the // VTK error. ls->m_VolumeRAY->ReleaseGraphicsResources(renderer->GetVtkRenderer()->GetRenderWindow()); ls->m_VolumeRAY = nullptr; ls->m_rayInitialized = false; } } void mitk::GPUVolumeMapper3D::GenerateDataRAY(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if (IsLODEnabled(renderer) && mitk::RenderingManager::GetInstance()->GetNextLOD(renderer) == 0) ls->m_MapperRAY->SetImageSampleDistance(4.0); else ls->m_MapperRAY->SetImageSampleDistance(1.0); // Check raycasting mode if (IsMIPEnabled(renderer)) ls->m_MapperRAY->SetBlendModeToMaximumIntensity(); else ls->m_MapperRAY->SetBlendModeToComposite(); // Updating shadings { float value = 0; if (GetDataNode()->GetFloatProperty("volumerendering.ray.ambient", value, renderer)) ls->m_VolumePropertyRAY->SetAmbient(value); if (GetDataNode()->GetFloatProperty("volumerendering.ray.diffuse", value, renderer)) ls->m_VolumePropertyRAY->SetDiffuse(value); if (GetDataNode()->GetFloatProperty("volumerendering.ray.specular", value, renderer)) ls->m_VolumePropertyRAY->SetSpecular(value); if (GetDataNode()->GetFloatProperty("volumerendering.ray.specular.power", value, renderer)) ls->m_VolumePropertyRAY->SetSpecularPower(value); } } bool mitk::GPUVolumeMapper3D::IsRAYEnabled(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool value = false; return ls->m_raySupported && GetDataNode()->GetBoolProperty("volumerendering.useray", value, renderer) && value; } - -#endif diff --git a/Modules/MapperExt/src/mitkVolumeMapperVtkSmart3D.cpp b/Modules/MapperExt/src/mitkVolumeMapperVtkSmart3D.cpp new file mode 100644 index 0000000000..8b254c25d6 --- /dev/null +++ b/Modules/MapperExt/src/mitkVolumeMapperVtkSmart3D.cpp @@ -0,0 +1,255 @@ +/*=================================================================== + +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 "mitkVolumeMapperVtkSmart3D.h" +#include "mitkTransferFunctionProperty.h" +#include "mitkTransferFunctionInitializer.h" +#include "mitkLevelWindowProperty.h" +#include +#include +#include +#include +#include + +void mitk::VolumeMapperVtkSmart3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) +{ + if (this->GetDataNode()->GetMTime() < this->GetMTime()) + { + return; + } + + bool value; + this->GetDataNode()->GetBoolProperty("volumerendering", value, renderer); + if (!value) + { + m_Volume->VisibilityOff(); + return; + } + else + { + m_Volume->VisibilityOn(); + } + + UpdateTransferFunctions(renderer); + UpdateRenderMode(renderer); + this->Modified(); +} + +vtkProp* mitk::VolumeMapperVtkSmart3D::GetVtkProp(mitk::BaseRenderer *renderer) +{ + if (!m_Volume->GetMapper()) + { + createMapper(GetInputImage()); + createVolume(); + createVolumeProperty(); + } + + return m_Volume; +} + +void mitk::VolumeMapperVtkSmart3D::ApplyProperties(vtkActor *actor, mitk::BaseRenderer *renderer) +{ + +} + +void mitk::VolumeMapperVtkSmart3D::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) +{ + // GPU_INFO << "SetDefaultProperties"; + + node->AddProperty("volumerendering", mitk::BoolProperty::New(false), renderer, overwrite); + node->AddProperty("volumerendering.usemip", mitk::BoolProperty::New(false), renderer, overwrite); + + node->AddProperty("volumerendering.cpu.ambient", mitk::FloatProperty::New(0.10f), renderer, overwrite); + node->AddProperty("volumerendering.cpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); + node->AddProperty("volumerendering.cpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); + node->AddProperty("volumerendering.cpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); + node->AddProperty("volumerendering.usegpu", mitk::BoolProperty::New(false), renderer, overwrite); + node->AddProperty("volumerendering.useray", mitk::BoolProperty::New(false), renderer, overwrite); + + node->AddProperty("volumerendering.gpu.ambient", mitk::FloatProperty::New(0.25f), renderer, overwrite); + node->AddProperty("volumerendering.gpu.diffuse", mitk::FloatProperty::New(0.50f), renderer, overwrite); + node->AddProperty("volumerendering.gpu.specular", mitk::FloatProperty::New(0.40f), renderer, overwrite); + node->AddProperty("volumerendering.gpu.specular.power", mitk::FloatProperty::New(16.0f), renderer, overwrite); + + node->AddProperty("binary", mitk::BoolProperty::New(false), renderer, overwrite); + + mitk::Image::Pointer image = dynamic_cast(node->GetData()); + if (image.IsNotNull() && image->IsInitialized()) + { + if ((overwrite) || (node->GetProperty("levelwindow", renderer) == nullptr)) + { + mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); + mitk::LevelWindow levelwindow; + levelwindow.SetAuto(image); + levWinProp->SetLevelWindow(levelwindow); + node->SetProperty("levelwindow", levWinProp, renderer); + } + + if ((overwrite) || (node->GetProperty("TransferFunction", renderer) == nullptr)) + { + // add a default transfer function + mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); + mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(tf); + tfInit->SetTransferFunctionMode(0); + node->SetProperty("TransferFunction", mitk::TransferFunctionProperty::New(tf.GetPointer())); + } + } + + Superclass::SetDefaultProperties(node, renderer, overwrite); +} + +vtkImageData* mitk::VolumeMapperVtkSmart3D::GetInputImage() +{ + mitk::Image *input = const_cast(static_cast(this->GetDataNode()->GetData())); + vtkImageData* img = input->GetVtkImageData(this->GetTimestep()); + img->SetSpacing(1,1,1); + + return img; +} + +void mitk::VolumeMapperVtkSmart3D::createMapper(vtkImageData* imageData) +{ + m_SmartVolumeMapper->SetBlendModeToComposite(); + m_SmartVolumeMapper->SetInputData(imageData); +} + +void mitk::VolumeMapperVtkSmart3D::createVolume() +{ + m_Volume->VisibilityOff(); + m_Volume->SetMapper(m_SmartVolumeMapper); + m_Volume->SetProperty(m_VolumeProperty); +} + +void mitk::VolumeMapperVtkSmart3D::createVolumeProperty() +{ + m_VolumeProperty->ShadeOn(); + m_VolumeProperty->SetInterpolationType(VTK_LINEAR_INTERPOLATION); +} + +void mitk::VolumeMapperVtkSmart3D::UpdateTransferFunctions(mitk::BaseRenderer *renderer) +{ + vtkSmartPointer opacityTransferFunction; + vtkSmartPointer gradientTransferFunction; + vtkSmartPointer colorTransferFunction; + + bool isBinary = false; + + this->GetDataNode()->GetBoolProperty("binary", isBinary, renderer); + + if (isBinary) + { + colorTransferFunction = vtkSmartPointer::New(); + + float rgb[3]; + if (!GetDataNode()->GetColor(rgb, renderer)) + rgb[0] = rgb[1] = rgb[2] = 1; + colorTransferFunction->AddRGBPoint(0, rgb[0], rgb[1], rgb[2]); + colorTransferFunction->Modified(); + + opacityTransferFunction = vtkSmartPointer::New(); + gradientTransferFunction = vtkSmartPointer::New(); + } + else + { + mitk::TransferFunctionProperty *transferFunctionProp = + dynamic_cast(this->GetDataNode()->GetProperty("TransferFunction", renderer)); + + if (transferFunctionProp) + { + opacityTransferFunction = transferFunctionProp->GetValue()->GetScalarOpacityFunction(); + gradientTransferFunction = transferFunctionProp->GetValue()->GetGradientOpacityFunction(); + colorTransferFunction = transferFunctionProp->GetValue()->GetColorTransferFunction(); + } + else + { + opacityTransferFunction = vtkSmartPointer::New(); + gradientTransferFunction = vtkSmartPointer::New(); + colorTransferFunction = vtkSmartPointer::New(); + } + } + + m_VolumeProperty->SetColor(colorTransferFunction); + m_VolumeProperty->SetScalarOpacity(opacityTransferFunction); + m_VolumeProperty->SetGradientOpacity(gradientTransferFunction); +} + + +void mitk::VolumeMapperVtkSmart3D::UpdateRenderMode(mitk::BaseRenderer *renderer) +{ + bool usegpu = false; + bool useray = false; + bool usemip = false; + this->GetDataNode()->GetBoolProperty("volumerendering.usegpu", usegpu); + this->GetDataNode()->GetBoolProperty("volumerendering.useray", useray); + this->GetDataNode()->GetBoolProperty("volumerendering.usemip", usemip); + + if (usegpu) + m_SmartVolumeMapper->SetRequestedRenderModeToGPU(); + else if (useray) + m_SmartVolumeMapper->SetRequestedRenderModeToRayCast(); + else + m_SmartVolumeMapper->SetRequestedRenderModeToDefault(); + + int blendMode; + if (this->GetDataNode()->GetIntProperty("volumerendering.blendmode", blendMode)) + m_SmartVolumeMapper->SetBlendMode(blendMode); + else if (usemip) + m_SmartVolumeMapper->SetBlendMode(vtkSmartVolumeMapper::MAXIMUM_INTENSITY_BLEND); + + // shading parameter + if (m_SmartVolumeMapper->GetRequestedRenderMode() == vtkSmartVolumeMapper::GPURenderMode) + { + float value = 0; + if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.ambient", value, renderer)) + m_VolumeProperty->SetAmbient(value); + if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.diffuse", value, renderer)) + m_VolumeProperty->SetDiffuse(value); + if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.specular", value, renderer)) + m_VolumeProperty->SetSpecular(value); + if (this->GetDataNode()->GetFloatProperty("volumerendering.gpu.specular.power", value, renderer)) + m_VolumeProperty->SetSpecularPower(value); + } + else + { + float value = 0; + if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.ambient", value, renderer)) + m_VolumeProperty->SetAmbient(value); + if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.diffuse", value, renderer)) + m_VolumeProperty->SetDiffuse(value); + if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.specular", value, renderer)) + m_VolumeProperty->SetSpecular(value); + if (this->GetDataNode()->GetFloatProperty("volumerendering.cpu.specular.power", value, renderer)) + m_VolumeProperty->SetSpecularPower(value); + } +} + +mitk::VolumeMapperVtkSmart3D::VolumeMapperVtkSmart3D() +{ + vtkObjectFactory::RegisterFactory(vtkRenderingOpenGL2ObjectFactory::New()); + vtkObjectFactory::RegisterFactory(vtkRenderingVolumeOpenGL2ObjectFactory::New()); + + m_SmartVolumeMapper = vtkSmartPointer::New(); + m_SmartVolumeMapper->SetBlendModeToComposite(); + m_VolumeProperty = vtkSmartPointer::New(); + m_Volume = vtkSmartPointer::New(); +} + +mitk::VolumeMapperVtkSmart3D::~VolumeMapperVtkSmart3D() +{ + +} + + diff --git a/Modules/MapperExt/src/vtkMitkGPUVolumeRayCastMapper.cpp b/Modules/MapperExt/src/vtkMitkGPUVolumeRayCastMapper.cpp index 9f483a152f..e3c0a47f72 100644 --- a/Modules/MapperExt/src/vtkMitkGPUVolumeRayCastMapper.cpp +++ b/Modules/MapperExt/src/vtkMitkGPUVolumeRayCastMapper.cpp @@ -1,629 +1,624 @@ /*=================================================================== 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. ===================================================================*/ /*========================================================================= Program: Visualization Toolkit Module: $RCSfile: vtkMitkGPUVolumeRayCastMapper.cxx,v $ Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkMitkGPUVolumeRayCastMapper.h" - -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION == 5) && (VTK_MINOR_VERSION >= 6))) - #include "vtkCamera.h" #include "vtkCellData.h" #include "vtkCommand.h" // for VolumeMapperRender{Start|End|Progress}Event #include "vtkDataArray.h" #include "vtkGPUInfo.h" #include "vtkGPUInfoList.h" #include "vtkImageData.h" #include "vtkImageResample.h" #include "vtkMultiThreader.h" #include "vtkPointData.h" #include "vtkRenderWindow.h" #include "vtkRenderer.h" #include "vtkRendererCollection.h" #include "vtkTimerLog.h" #include "vtkVolume.h" #include "vtkVolumeProperty.h" #include vtkInstantiatorNewMacro(vtkMitkGPUVolumeRayCastMapper); vtkCxxSetObjectMacro(vtkMitkGPUVolumeRayCastMapper, MaskInput, vtkImageData); vtkCxxSetObjectMacro(vtkMitkGPUVolumeRayCastMapper, TransformedInput, vtkImageData); vtkMitkGPUVolumeRayCastMapper::vtkMitkGPUVolumeRayCastMapper() { this->AutoAdjustSampleDistances = 1; this->ImageSampleDistance = 1.0; this->MinimumImageSampleDistance = 1.0; this->MaximumImageSampleDistance = 10.0; this->SampleDistance = 1.0; this->SmallVolumeRender = 0; this->BigTimeToDraw = 0.0; this->SmallTimeToDraw = 0.0; this->FinalColorWindow = 1.0; this->FinalColorLevel = 0.5; this->GeneratingCanonicalView = 0; this->CanonicalViewImageData = nullptr; this->MaskInput = nullptr; this->MaskBlendFactor = 1.0f; this->AMRMode = 0; this->ClippedCroppingRegionPlanes[0] = VTK_DOUBLE_MAX; this->ClippedCroppingRegionPlanes[1] = VTK_DOUBLE_MIN; this->ClippedCroppingRegionPlanes[2] = VTK_DOUBLE_MAX; this->ClippedCroppingRegionPlanes[3] = VTK_DOUBLE_MIN; this->ClippedCroppingRegionPlanes[4] = VTK_DOUBLE_MAX; this->ClippedCroppingRegionPlanes[5] = VTK_DOUBLE_MIN; this->MaxMemoryInBytes = 0; vtkGPUInfoList *l = vtkGPUInfoList::New(); l->Probe(); if (l->GetNumberOfGPUs() > 0) { vtkGPUInfo *info = l->GetGPUInfo(0); this->MaxMemoryInBytes = info->GetDedicatedVideoMemory(); if (this->MaxMemoryInBytes == 0) { this->MaxMemoryInBytes = info->GetDedicatedSystemMemory(); } // we ignore info->GetSharedSystemMemory(); as this is very slow. } l->Delete(); if (this->MaxMemoryInBytes == 0) // use some default value: 128MB. { this->MaxMemoryInBytes = 128 * 1024 * 1024; } this->MaxMemoryFraction = 0.75; this->ReportProgress = true; this->TransformedInput = nullptr; this->LastInput = nullptr; } // ---------------------------------------------------------------------------- vtkMitkGPUVolumeRayCastMapper::~vtkMitkGPUVolumeRayCastMapper() { this->SetMaskInput(nullptr); this->SetTransformedInput(nullptr); this->LastInput = nullptr; } // ---------------------------------------------------------------------------- // The render method that is called from the volume. If this is a canonical // view render, a specialized version of this method will be called instead. // Otherwise we will // - Invoke a start event // - Start timing // - Check that everything is OK for rendering // - Render // - Stop the timer and record results // - Invoke an end event // ---------------------------------------------------------------------------- void vtkMitkGPUVolumeRayCastMapper::Render(vtkRenderer *ren, vtkVolume *vol) { // Catch renders that are happening due to a canonical view render and // handle them separately. if (this->GeneratingCanonicalView) { this->CanonicalViewRender(ren, vol); return; } // Invoke a VolumeMapperRenderStartEvent this->InvokeEvent(vtkCommand::VolumeMapperRenderStartEvent, nullptr); // Start the timer to time the length of this render vtkTimerLog *timer = vtkTimerLog::New(); timer->StartTimer(); // Make sure everything about this render is OK. // This is where the input is updated. if (this->ValidateRender(ren, vol)) { // Everything is OK - so go ahead and really do the render this->GPURender(ren, vol); } // Stop the timer timer->StopTimer(); double t = timer->GetElapsedTime(); // cout << "Render Timer " << t << " seconds, " << 1.0/t << " frames per second" << endl; this->TimeToDraw = t; timer->Delete(); if (vol->GetAllocatedRenderTime() < 1.0) { this->SmallTimeToDraw = t; } else { this->BigTimeToDraw = t; } // Invoke a VolumeMapperRenderEndEvent this->InvokeEvent(vtkCommand::VolumeMapperRenderEndEvent, nullptr); } // ---------------------------------------------------------------------------- // Special version for rendering a canonical view - we don't do things like // invoke start or end events, and we don't capture the render time. // ---------------------------------------------------------------------------- void vtkMitkGPUVolumeRayCastMapper::CanonicalViewRender(vtkRenderer *ren, vtkVolume *vol) { // Make sure everything about this render is OK if (this->ValidateRender(ren, vol)) { // Everything is OK - so go ahead and really do the render this->GPURender(ren, vol); } } // ---------------------------------------------------------------------------- // This method us used by the render method to validate everything before // attempting to render. This method returns 0 if something is not right - // such as missing input, a null renderer or a null volume, no scalars, etc. // In some cases it will produce a vtkErrorMacro message, and in others // (for example, in the case of cropping planes that define a region with // a volume or 0 or less) it will fail silently. If everything is OK, it will // return with a value of 1. // ---------------------------------------------------------------------------- int vtkMitkGPUVolumeRayCastMapper::ValidateRender(vtkRenderer *ren, vtkVolume *vol) { // Check that we have everything we need to render. int goodSoFar = 1; // Check for a renderer - we MUST have one if (!ren) { goodSoFar = 0; vtkErrorMacro("Renderer cannot be null."); } // Check for the volume - we MUST have one if (goodSoFar && !vol) { goodSoFar = 0; vtkErrorMacro("Volume cannot be null."); } // Don't need to check if we have a volume property // since the volume will create one if we don't. Also // don't need to check for the scalar opacity function // or the RGB transfer function since the property will // create them if they do not yet exist. // However we must currently check that the number of // color channels is 3 // TODO: lift this restriction - should work with // gray functions as well. Right now turning off test // because otherwise 4 component rendering isn't working. // Will revisit. if (goodSoFar && vol->GetProperty()->GetColorChannels() != 3) { // goodSoFar = 0; // vtkErrorMacro("Must have a color transfer function."); } // Check the cropping planes. If they are invalid, just silently // fail. This will happen when an interactive widget is dragged // such that it defines 0 or negative volume - this can happen // and should just not render the volume. // Check the cropping planes if (goodSoFar && this->Cropping && (this->CroppingRegionPlanes[0] >= this->CroppingRegionPlanes[1] || this->CroppingRegionPlanes[2] >= this->CroppingRegionPlanes[3] || this->CroppingRegionPlanes[4] >= this->CroppingRegionPlanes[5])) { // No error message here - we want to be silent goodSoFar = 0; } // Check that we have input data vtkImageData *input = this->GetInput(); // If we have a timestamp change or data change then create a new clone. if (input != this->LastInput || input->GetMTime() > this->TransformedInput->GetMTime()) { this->LastInput = input; vtkImageData *clone; if (!this->TransformedInput) { clone = vtkImageData::New(); this->SetTransformedInput(clone); clone->Delete(); } else { clone = this->TransformedInput; } clone->ShallowCopy(input); // @TODO: This is the workaround to deal with GPUVolumeRayCastMapper // not able to handle extents starting from non zero values. // There is not a easy fix in the GPU volume ray cast mapper hence // this fix has been introduced. // Get the current extents. int extents[6], real_extents[6]; clone->GetExtent(extents); clone->GetExtent(real_extents); // Get the current origin and spacing. double origin[3], spacing[3]; clone->GetOrigin(origin); clone->GetSpacing(spacing); for (int cc = 0; cc < 3; cc++) { // Transform the origin and the extents. origin[cc] = origin[cc] + extents[2 * cc] * spacing[cc]; extents[2 * cc + 1] -= extents[2 * cc]; extents[2 * cc] -= extents[2 * cc]; } clone->SetOrigin(origin); clone->SetExtent(extents); } if (goodSoFar && !this->TransformedInput) { vtkErrorMacro("Input is nullptr but is required"); goodSoFar = 0; } // Update the date then make sure we have scalars. Note // that we must have point or cell scalars because field // scalars are not supported. vtkDataArray *scalars = nullptr; if (goodSoFar) { // Here is where we update the input // this->TransformedInput->UpdateInformation(); //VTK6_TODO // this->TransformedInput->SetUpdateExtentToWholeExtent(); // this->TransformedInput->Update(); // Now make sure we can find scalars scalars = this->GetScalars( this->TransformedInput, this->ScalarMode, this->ArrayAccessMode, this->ArrayId, this->ArrayName, this->CellFlag); // We couldn't find scalars if (!scalars) { vtkErrorMacro("No scalars found on input."); goodSoFar = 0; } // Even if we found scalars, if they are field data scalars that isn't good else if (this->CellFlag == 2) { vtkErrorMacro("Only point or cell scalar support - found field scalars instead."); goodSoFar = 0; } } // Make sure the scalar type is actually supported. This mappers supports // almost all standard scalar types. if (goodSoFar) { switch (scalars->GetDataType()) { case VTK_CHAR: vtkErrorMacro(<< "scalar of type VTK_CHAR is not supported " << "because this type is platform dependent. " << "Use VTK_SIGNED_CHAR or VTK_UNSIGNED_CHAR instead."); goodSoFar = 0; break; case VTK_BIT: vtkErrorMacro("scalar of type VTK_BIT is not supported by this mapper."); goodSoFar = 0; break; case VTK_ID_TYPE: vtkErrorMacro("scalar of type VTK_ID_TYPE is not supported by this mapper."); goodSoFar = 0; break; case VTK_STRING: vtkErrorMacro("scalar of type VTK_STRING is not supported by this mapper."); goodSoFar = 0; break; default: // Don't need to do anything here break; } } // Check on the blending type - we support composite and min / max intensity if (goodSoFar) { if (this->BlendMode != vtkVolumeMapper::COMPOSITE_BLEND && this->BlendMode != vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND && this->BlendMode != vtkVolumeMapper::MINIMUM_INTENSITY_BLEND) { goodSoFar = 0; vtkErrorMacro(<< "Selected blend mode not supported. " << "Only Composite and MIP and MinIP modes " << "are supported by the current implementation."); } } // This mapper supports 1 component data, or 4 component if it is not independent // component (i.e. the four components define RGBA) int numberOfComponents = 0; if (goodSoFar) { numberOfComponents = scalars->GetNumberOfComponents(); if (!(numberOfComponents == 1 || (numberOfComponents == 4 && vol->GetProperty()->GetIndependentComponents() == 0))) { goodSoFar = 0; vtkErrorMacro(<< "Only one component scalars, or four " << "component with non-independent components, " << "are supported by this mapper."); } } // If this is four component data, then it better be unsigned char (RGBA). if (goodSoFar && numberOfComponents == 4 && scalars->GetDataType() != VTK_UNSIGNED_CHAR) { goodSoFar = 0; vtkErrorMacro("Only unsigned char is supported for 4-component scalars!"); } // return our status return goodSoFar; } // ---------------------------------------------------------------------------- // Description: // Called by the AMR Volume Mapper. // Set the flag that tells if the scalars are on point data (0) or // cell data (1). void vtkMitkGPUVolumeRayCastMapper::SetCellFlag(int cellFlag) { this->CellFlag = cellFlag; } // ---------------------------------------------------------------------------- void vtkMitkGPUVolumeRayCastMapper::CreateCanonicalView(vtkRenderer *ren, vtkVolume *volume, vtkImageData *image, int vtkNotUsed(blend_mode), double viewDirection[3], double viewUp[3]) { this->GeneratingCanonicalView = 1; int oldSwap = ren->GetRenderWindow()->GetSwapBuffers(); ren->GetRenderWindow()->SwapBuffersOff(); int dim[3]; image->GetDimensions(dim); int *size = ren->GetRenderWindow()->GetSize(); vtkImageData *bigImage = vtkImageData::New(); bigImage->SetDimensions(size[0], size[1], 1); bigImage->AllocateScalars(VTK_UNSIGNED_CHAR, 3); this->CanonicalViewImageData = bigImage; double scale[2]; scale[0] = dim[0] / static_cast(size[0]); scale[1] = dim[1] / static_cast(size[1]); // Save the visibility flags of the renderers and set all to false except // for the ren. vtkRendererCollection *renderers = ren->GetRenderWindow()->GetRenderers(); int numberOfRenderers = renderers->GetNumberOfItems(); auto rendererVisibilities = new bool[numberOfRenderers]; renderers->InitTraversal(); int i = 0; while (i < numberOfRenderers) { vtkRenderer *r = renderers->GetNextItem(); rendererVisibilities[i] = r->GetDraw() == 1; if (r != ren) { r->SetDraw(false); } ++i; } // Save the visibility flags of the props and set all to false except // for the volume. vtkPropCollection *props = ren->GetViewProps(); int numberOfProps = props->GetNumberOfItems(); auto propVisibilities = new bool[numberOfProps]; props->InitTraversal(); i = 0; while (i < numberOfProps) { vtkProp *p = props->GetNextProp(); propVisibilities[i] = p->GetVisibility() == 1; if (p != volume) { p->SetVisibility(false); } ++i; } vtkCamera *savedCamera = ren->GetActiveCamera(); savedCamera->Modified(); vtkCamera *canonicalViewCamera = vtkCamera::New(); // Code from vtkFixedPointVolumeRayCastMapper: double *center = volume->GetCenter(); double bounds[6]; volume->GetBounds(bounds); double d = sqrt((bounds[1] - bounds[0]) * (bounds[1] - bounds[0]) + (bounds[3] - bounds[2]) * (bounds[3] - bounds[2]) + (bounds[5] - bounds[4]) * (bounds[5] - bounds[4])); // For now use x distance - need to change this d = bounds[1] - bounds[0]; // Set up the camera in parallel canonicalViewCamera->SetFocalPoint(center); canonicalViewCamera->ParallelProjectionOn(); canonicalViewCamera->SetPosition( center[0] - d * viewDirection[0], center[1] - d * viewDirection[1], center[2] - d * viewDirection[2]); canonicalViewCamera->SetViewUp(viewUp); canonicalViewCamera->SetParallelScale(d / 2); ren->SetActiveCamera(canonicalViewCamera); ren->GetRenderWindow()->Render(); ren->SetActiveCamera(savedCamera); canonicalViewCamera->Delete(); // Shrink to image to the desired size vtkImageResample *resample = vtkImageResample::New(); resample->SetInputData(bigImage); resample->SetAxisMagnificationFactor(0, scale[0]); resample->SetAxisMagnificationFactor(1, scale[1]); resample->SetAxisMagnificationFactor(2, 1); resample->UpdateWholeExtent(); // Copy the pixels over image->DeepCopy(resample->GetOutput()); bigImage->Delete(); resample->Delete(); // Restore the visibility flags of the props props->InitTraversal(); i = 0; while (i < numberOfProps) { vtkProp *p = props->GetNextProp(); p->SetVisibility(propVisibilities[i]); ++i; } delete[] propVisibilities; // Restore the visibility flags of the renderers renderers->InitTraversal(); i = 0; while (i < numberOfRenderers) { vtkRenderer *r = renderers->GetNextItem(); r->SetDraw(rendererVisibilities[i]); ++i; } delete[] rendererVisibilities; ren->GetRenderWindow()->SetSwapBuffers(oldSwap); this->CanonicalViewImageData = nullptr; this->GeneratingCanonicalView = 0; } // ---------------------------------------------------------------------------- // Print method for vtkMitkGPUVolumeRayCastMapper void vtkMitkGPUVolumeRayCastMapper::PrintSelf(ostream &os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "AutoAdjustSampleDistances: " << this->AutoAdjustSampleDistances << endl; os << indent << "MinimumImageSampleDistance: " << this->MinimumImageSampleDistance << endl; os << indent << "MaximumImageSampleDistance: " << this->MaximumImageSampleDistance << endl; os << indent << "ImageSampleDistance: " << this->ImageSampleDistance << endl; os << indent << "SampleDistance: " << this->SampleDistance << endl; os << indent << "FinalColorWindow: " << this->FinalColorWindow << endl; os << indent << "FinalColorLevel: " << this->FinalColorLevel << endl; os << indent << "MaskInput: " << this->MaskInput << endl; os << indent << "MaskBlendFactor: " << this->MaskBlendFactor << endl; os << indent << "MaxMemoryInBytes: " << this->MaxMemoryInBytes << endl; os << indent << "MaxMemoryFraction: " << this->MaxMemoryFraction << endl; os << indent << "ReportProgress: " << this->ReportProgress << endl; } // ---------------------------------------------------------------------------- // Description: // Compute the cropping planes clipped by the bounds of the volume. // The result is put into this->ClippedCroppingRegionPlanes. // NOTE: IT WILL BE MOVED UP TO vtkVolumeMapper after bullet proof usage // in this mapper. Other subclasses will use the ClippedCroppingRegionsPlanes // members instead of CroppingRegionPlanes. // \pre volume_exists: this->GetInput()!=0 // \pre valid_cropping: this->Cropping && // this->CroppingRegionPlanes[0]CroppingRegionPlanes[1] && // this->CroppingRegionPlanes[2]CroppingRegionPlanes[3] && // this->CroppingRegionPlanes[4]CroppingRegionPlanes[5]) void vtkMitkGPUVolumeRayCastMapper::ClipCroppingRegionPlanes() { assert("pre: volume_exists" && this->GetInput() != nullptr); assert("pre: valid_cropping" && this->Cropping && this->CroppingRegionPlanes[0] < this->CroppingRegionPlanes[1] && this->CroppingRegionPlanes[2] < this->CroppingRegionPlanes[3] && this->CroppingRegionPlanes[4] < this->CroppingRegionPlanes[5]); // vtkVolumeMapper::Render() will have something like: // if(this->Cropping && (this->CroppingRegionPlanes[0]>=this->CroppingRegionPlanes[1] || // this->CroppingRegionPlanes[2]>=this->CroppingRegionPlanes[3] || // this->CroppingRegionPlanes[4]>=this->CroppingRegionPlanes[5])) // { // // silentely stop because the cropping is not valid. // return; // } double volBounds[6]; this->GetInput()->GetBounds(volBounds); int i = 0; while (i < 6) { // max of the mins if (this->CroppingRegionPlanes[i] < volBounds[i]) { this->ClippedCroppingRegionPlanes[i] = volBounds[i]; } else { this->ClippedCroppingRegionPlanes[i] = this->CroppingRegionPlanes[i]; } ++i; // min of the maxs if (this->CroppingRegionPlanes[i] > volBounds[i]) { this->ClippedCroppingRegionPlanes[i] = volBounds[i]; } + else { this->ClippedCroppingRegionPlanes[i] = this->CroppingRegionPlanes[i]; } ++i; } } - -#endif diff --git a/Modules/MapperExt/src/vtkPointSetSlicer.cxx b/Modules/MapperExt/src/vtkPointSetSlicer.cxx index 8d433c392f..8c6930f5be 100644 --- a/Modules/MapperExt/src/vtkPointSetSlicer.cxx +++ b/Modules/MapperExt/src/vtkPointSetSlicer.cxx @@ -1,638 +1,638 @@ /*=================================================================== 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 #include "vtkPointSetSlicer.h" #include "vtkCellArray.h" #include "vtkCellData.h" #include "vtkCutter.h" #include "vtkDataSet.h" #include "vtkDoubleArray.h" #include "vtkFloatArray.h" #include "vtkGenericCell.h" #include "vtkMergePoints.h" #include "vtkObjectFactory.h" #include "vtkPlane.h" #include "vtkPointData.h" #include "vtkPolyData.h" #include "vtkUnstructuredGrid.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkStreamingDemandDrivenPipeline.h" vtkStandardNewMacro(vtkPointSetSlicer); // Construct with user-specified implicit function; initial value of 0.0; and // generating cut scalars turned off. vtkPointSetSlicer::vtkPointSetSlicer(vtkPlane *cf) { this->SlicePlane = cf; this->GenerateCutScalars = 0; this->Locator = 0; this->Cutter = vtkCutter::New(); this->Cutter->GenerateValues(1, 0, 1); } vtkPointSetSlicer::~vtkPointSetSlicer() { this->SetSlicePlane(0); if (this->Locator) { this->Locator->UnRegister(this); this->Locator = NULL; } this->Cutter->Delete(); } void vtkPointSetSlicer::SetSlicePlane(vtkPlane *plane) { if (this->SlicePlane == plane) { return; } if (this->SlicePlane) { this->SlicePlane->UnRegister(this); this->SlicePlane = 0; } if (plane) { plane->Register(this); this->Cutter->SetCutFunction(plane); } this->SlicePlane = plane; this->Modified(); } // Overload standard modified time function. If cut functions is modified, // or contour values modified, then this object is modified as well. -unsigned long vtkPointSetSlicer::GetMTime() +vtkMTimeType vtkPointSetSlicer::GetMTime() { - unsigned long mTime = this->Superclass::GetMTime(); - unsigned long time; + vtkMTimeType mTime = this->Superclass::GetMTime(); + vtkMTimeType time; if (this->SlicePlane != 0) { time = this->SlicePlane->GetMTime(); mTime = (time > mTime ? time : mTime); } if (this->Locator != 0) { time = this->Locator->GetMTime(); mTime = (time > mTime ? time : mTime); } return mTime; } int vtkPointSetSlicer::RequestData(vtkInformation * /*request*/, vtkInformationVector **inputVector, vtkInformationVector *outputVector) { // get the info objects vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); vtkInformation *outInfo = outputVector->GetInformationObject(0); // get the input and ouptut vtkDataSet *input = vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); vtkPolyData *output = vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); vtkDebugMacro(<< "Executing cutter"); if (!this->SlicePlane) { vtkErrorMacro("No slice plane specified"); return 0; } if (input->GetNumberOfPoints() < 1) { return 1; } if (input->GetDataObjectType() == VTK_STRUCTURED_POINTS || input->GetDataObjectType() == VTK_IMAGE_DATA) { if (input->GetCell(0) && input->GetCell(0)->GetCellDimension() >= 3) { // this->StructuredPointsCutter(input, output, request, inputVector, outputVector); return 1; } } if (input->GetDataObjectType() == VTK_STRUCTURED_GRID) { if (input->GetCell(0)) { int dim = input->GetCell(0)->GetCellDimension(); // only do 3D structured grids (to be extended in the future) if (dim >= 3) { // this->StructuredGridCutter(input, output); return 1; } } } if (input->GetDataObjectType() == VTK_RECTILINEAR_GRID) { // this->RectilinearGridCutter(input, output); return 1; } if (input->GetDataObjectType() == VTK_UNSTRUCTURED_GRID) { vtkDebugMacro(<< "Executing Unstructured Grid Cutter"); this->UnstructuredGridCutter(input, output); } else { vtkDebugMacro(<< "Executing DataSet Cutter"); // this->DataSetCutter(input, output); } return 1; } int vtkPointSetSlicer::RequestUpdateExtent(vtkInformation *, vtkInformationVector **inputVector, vtkInformationVector *) { vtkInformation *inInfo = inputVector[0]->GetInformationObject(0); inInfo->Set(vtkStreamingDemandDrivenPipeline::EXACT_EXTENT(), 1); return 1; } int vtkPointSetSlicer::FillInputPortInformation(int, vtkInformation *info) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); return 1; } void vtkPointSetSlicer::UnstructuredGridCutter(vtkDataSet *input, vtkPolyData *output) { vtkIdType cellId, i; vtkDoubleArray *cellScalars; vtkCellArray *newVerts, *newLines, *newPolys; vtkPoints *newPoints; vtkDoubleArray *cutScalars; double s; vtkIdType estimatedSize, numCells = input->GetNumberOfCells(); vtkIdType numPts = input->GetNumberOfPoints(); vtkIdType cellArrayIt = 0; int numCellPts; vtkPointData *inPD, *outPD; vtkCellData *inCD = input->GetCellData(), *outCD = output->GetCellData(); vtkIdList *cellIds; int abortExecute = 0; double range[2]; // Create objects to hold output of contour operation // estimatedSize = (vtkIdType)pow((double)numCells, .75); estimatedSize = estimatedSize / 1024 * 1024; // multiple of 1024 if (estimatedSize < 1024) { estimatedSize = 1024; } newPoints = vtkPoints::New(); newPoints->Allocate(estimatedSize, estimatedSize / 2); newVerts = vtkCellArray::New(); newVerts->Allocate(estimatedSize, estimatedSize / 2); newLines = vtkCellArray::New(); newLines->Allocate(estimatedSize, estimatedSize / 2); newPolys = vtkCellArray::New(); newPolys->Allocate(estimatedSize, estimatedSize / 2); cutScalars = vtkDoubleArray::New(); cutScalars->SetNumberOfTuples(numPts); // Interpolate data along edge. If generating cut scalars, do necessary setup if (this->GenerateCutScalars) { inPD = vtkPointData::New(); inPD->ShallowCopy(input->GetPointData()); // copies original attributes inPD->SetScalars(cutScalars); } else { inPD = input->GetPointData(); } outPD = output->GetPointData(); outPD->InterpolateAllocate(inPD, estimatedSize, estimatedSize / 2); outCD->CopyAllocate(inCD, estimatedSize, estimatedSize / 2); // locator used to merge potentially duplicate points if (this->Locator == NULL) { this->CreateDefaultLocator(); } this->Locator->InitPointInsertion(newPoints, input->GetBounds()); // Loop over all points evaluating scalar function at each point // for (i = 0; i < numPts; i++) { s = this->SlicePlane->FunctionValue(input->GetPoint(i)); cutScalars->SetComponent(i, 0, s); } // Compute some information for progress methods // vtkIdType numCuts = numCells; vtkIdType progressInterval = numCuts / 20 + 1; int cut = 0; vtkUnstructuredGrid *grid = (vtkUnstructuredGrid *)input; vtkIdType *cellArrayPtr = grid->GetCells()->GetPointer(); double *scalarArrayPtr = cutScalars->GetPointer(0); double tempScalar; cellScalars = cutScalars->NewInstance(); cellScalars->SetNumberOfComponents(cutScalars->GetNumberOfComponents()); cellScalars->Allocate(VTK_CELL_SIZE * cutScalars->GetNumberOfComponents()); // Three passes over the cells to process lower dimensional cells first. // For poly data output cells need to be added in the order: // verts, lines and then polys, or cell data gets mixed up. // A better solution is to have an unstructured grid output. // I create a table that maps cell type to cell dimensionality, // because I need a fast way to get cell dimensionality. // This assumes GetCell is slow and GetCellType is fast. // I do not like hard coding a list of cell types here, // but I do not want to add GetCellDimension(vtkIdType cellId) // to the vtkDataSet API. Since I anticipate that the output // will change to vtkUnstructuredGrid. This temporary solution // is acceptable. // int cellType; unsigned char cellTypeDimensions[VTK_NUMBER_OF_CELL_TYPES]; vtkCutter::GetCellTypeDimensions(cellTypeDimensions); int dimensionality; // We skip 0d cells (points), because they cannot be cut (generate no data). for (dimensionality = 1; dimensionality <= 3; ++dimensionality) { // Loop over all cells; get scalar values for all cell points // and process each cell. // cellArrayIt = 0; for (cellId = 0; cellId < numCells && !abortExecute; cellId++) { numCellPts = cellArrayPtr[cellArrayIt]; // I assume that "GetCellType" is fast. cellType = input->GetCellType(cellId); if (cellType >= VTK_NUMBER_OF_CELL_TYPES) { // Protect against new cell types added. vtkErrorMacro("Unknown cell type " << cellType); cellArrayIt += 1 + numCellPts; continue; } if (cellTypeDimensions[cellType] != dimensionality) { cellArrayIt += 1 + numCellPts; continue; } cellArrayIt++; // find min and max values in scalar data range[0] = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; range[1] = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; cellArrayIt++; for (i = 1; i < numCellPts; i++) { tempScalar = scalarArrayPtr[cellArrayPtr[cellArrayIt]]; cellArrayIt++; if (tempScalar <= range[0]) { range[0] = tempScalar; } // if tempScalar <= min range value if (tempScalar >= range[1]) { range[1] = tempScalar; } // if tempScalar >= max range value } // for all points in this cell int needCell = 0; if (0.0 >= range[0] && 0.0 <= range[1]) { needCell = 1; } if (needCell) { vtkCell *cell = input->GetCell(cellId); cellIds = cell->GetPointIds(); cutScalars->GetTuples(cellIds, cellScalars); // Loop over all contour values. if (dimensionality == 3 && !(++cut % progressInterval)) { vtkDebugMacro(<< "Cutting #" << cut); this->UpdateProgress(static_cast(cut) / numCuts); abortExecute = this->GetAbortExecute(); } this->ContourUnstructuredGridCell( cell, cellScalars, this->Locator, newVerts, newLines, newPolys, inPD, outPD, inCD, cellId, outCD); } // if need cell } // for all cells } // for all dimensions (1,2,3). // Update ourselves. Because we don't know upfront how many verts, lines, // polys we've created, take care to reclaim memory. // cellScalars->Delete(); cutScalars->Delete(); if (this->GenerateCutScalars) { inPD->Delete(); } output->SetPoints(newPoints); newPoints->Delete(); if (newVerts->GetNumberOfCells()) { output->SetVerts(newVerts); } newVerts->Delete(); if (newLines->GetNumberOfCells()) { output->SetLines(newLines); } newLines->Delete(); if (newPolys->GetNumberOfCells()) { output->SetPolys(newPolys); } newPolys->Delete(); this->Locator->Initialize(); // release any extra memory output->Squeeze(); } void vtkPointSetSlicer::ContourUnstructuredGridCell(vtkCell *cell, vtkDataArray *cellScalars, vtkPointLocator *locator, vtkCellArray *verts, vtkCellArray *lines, vtkCellArray *polys, vtkPointData *inPd, vtkPointData *outPd, vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd) { if (cell->GetCellType() == VTK_HEXAHEDRON) { static int CASE_MASK[8] = {1, 2, 4, 8, 16, 32, 64, 128}; POLY_CASES *polyCase; EDGE_LIST *edge; int i, j, index, *vert; volatile int pnum; int v1, v2, newCellId; double t, x1[3], x2[3], x[3], deltaScalar; vtkIdType offset = verts->GetNumberOfCells() + lines->GetNumberOfCells(); // Build the case table for (i = 0, index = 0; i < 8; i++) { if (cellScalars->GetComponent(i, 0) >= 0) { index |= CASE_MASK[i]; } } polyCase = polyCases + index; edge = polyCase->edges; // get the point number of the polygon pnum = 0; for (i = 0; i < 8; i++) if (edge[i] > -1) pnum++; else break; vtkIdType *pts = new vtkIdType[pnum]; for (i = 0; i < pnum; i++) // insert polygon { vert = edges[edge[i]]; // calculate a preferred interpolation direction deltaScalar = (cellScalars->GetComponent(vert[1], 0) - cellScalars->GetComponent(vert[0], 0)); if (deltaScalar > 0) { v1 = vert[0]; v2 = vert[1]; } else { v1 = vert[1]; v2 = vert[0]; deltaScalar = -deltaScalar; } // linear interpolation t = (deltaScalar == 0.0 ? 0.0 : (-cellScalars->GetComponent(v1, 0)) / deltaScalar); cell->GetPoints()->GetPoint(v1, x1); cell->GetPoints()->GetPoint(v2, x2); for (j = 0; j < 3; j++) { x[j] = x1[j] + t * (x2[j] - x1[j]); } if (locator->InsertUniquePoint(x, pts[i])) { if (outPd) { vtkIdType p1 = cell->GetPointIds()->GetId(v1); vtkIdType p2 = cell->GetPointIds()->GetId(v2); outPd->InterpolateEdge(inPd, pts[i], p1, p2, t); } } } // check for degenerate polygon std::vector pset; for (i = 0; i < pnum; i++) { if (std::find(pset.begin(), pset.end(), pts[i]) == pset.end()) pset.push_back(pts[i]); } if (pset.size() > 2) { i = 0; for (std::vector::iterator iter = pset.begin(); iter != pset.end(); iter++) { pts[i] = *iter; i++; } newCellId = offset + polys->InsertNextCell(pset.size(), pts); outCd->CopyData(inCd, cellId, newCellId); } delete[] pts; } else { cell->Contour(0, cellScalars, locator, verts, lines, polys, inPd, outPd, inCd, cellId, outCd); } } // Specify a spatial locator for merging points. By default, // an instance of vtkMergePoints is used. void vtkPointSetSlicer::SetLocator(vtkPointLocator *locator) { if (this->Locator == locator) { return; } if (this->Locator) { this->Locator->UnRegister(this); this->Locator = 0; } if (locator) { locator->Register(this); } this->Locator = locator; this->Modified(); } void vtkPointSetSlicer::CreateDefaultLocator() { if (this->Locator == 0) { this->Locator = vtkMergePoints::New(); this->Locator->Register(this); this->Locator->Delete(); } } void vtkPointSetSlicer::PrintSelf(std::ostream &os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "Slice Plane: " << this->SlicePlane << "\n"; if (this->Locator) { os << indent << "Locator: " << this->Locator << "\n"; } else { os << indent << "Locator: (none)\n"; } os << indent << "Generate Cut Scalars: " << (this->GenerateCutScalars ? "On\n" : "Off\n"); } int vtkPointSetSlicer::edges[12][2] = { {0, 1}, {1, 2}, {3, 2}, {0, 3}, {4, 5}, {5, 6}, {7, 6}, {4, 7}, {0, 4}, {1, 5}, {2, 6}, {3, 7}}; vtkPointSetSlicer::POLY_CASES vtkPointSetSlicer::polyCases[256] = { {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 3, 8, -1, -1, -1, -1, -1}}, {{1, 0, 9, -1, -1, -1, -1, -1}}, {{1, 3, 8, 9, -1, -1, -1, -1}}, {{2, 1, 10, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 0, 9, 10, -1, -1, -1, -1}}, {{2, 10, 9, 8, 3, -1, -1, -1}}, {{3, 2, 11, -1, -1, -1, -1, -1}}, {{0, 2, 11, 8, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 9, 8, 11, 2, -1, -1, -1}}, {{3, 1, 10, 11, -1, -1, -1, -1}}, {{0, 8, 11, 10, 1, -1, -1, -1}}, {{3, 11, 10, 9, 0, -1, -1, -1}}, {{8, 9, 10, 11, -1, -1, -1, -1}}, {{4, 7, 8, -1, -1, -1, -1, -1}}, {{3, 7, 4, 0, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 1, 3, 7, 4, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{11, 2, 0, 4, 7, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 2, 11, 7, 4, 9, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 7, 11, 10, 9, -1, -1, -1}}, {{5, 4, 9, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{0, 4, 5, 1, -1, -1, -1, -1}}, {{8, 3, 1, 5, 4, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 2, 0, 4, 5, -1, -1, -1}}, {{2, 3, 8, 4, 5, 10, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{5, 4, 8, 11, 10, -1, -1, -1}}, {{5, 7, 8, 9, -1, -1, -1, -1}}, {{9, 5, 7, 3, 0, -1, -1, -1}}, {{8, 7, 5, 1, 0, -1, -1, -1}}, {{1, 3, 7, 5, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 10, 5, 7, 3, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 11, 7, 5, 1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{5, 7, 11, 10, -1, -1, -1, -1}}, {{6, 5, 10, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 5, 6, 2, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 0, 2, 6, 5, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{11, 3, 1, 5, 6, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 0, 9, 5, 6, 11, -1, -1}}, {{6, 5, 9, 8, 11, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{6, 4, 9, 10, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 6, 4, 0, 1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{9, 4, 6, 2, 1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 0, 4, 6, -1, -1, -1, -1}}, {{3, 8, 4, 6, 2, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 11, 6, 4, 0, -1, -1, -1}}, {{6, 4, 8, 11, -1, -1, -1, -1}}, {{6, 10, 9, 8, 7, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{6, 7, 8, 0, 1, 10, -1, -1}}, {{6, 10, 1, 3, 7, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 8, 0, 2, 6, -1, -1, -1}}, {{2, 6, 7, 3, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{6, 7, 11, -1, -1, -1, -1, -1}}, {{7, 6, 11, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 6, 7, 3, -1, -1, -1, -1}}, {{8, 0, 2, 6, 7, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 1, 3, 7, 6, -1, -1, -1}}, {{0, 1, 10, 6, 7, 8, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 6, 10, 9, 8, -1, -1, -1}}, {{4, 6, 11, 8, -1, -1, -1, -1}}, {{11, 6, 4, 0, 3, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{8, 4, 6, 2, 3, -1, -1, -1}}, {{0, 2, 6, 4, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 9, 4, 6, 2, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 10, 6, 4, 0, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 6, 10, 9, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{5, 9, 8, 11, 6, -1, -1, -1}}, {{5, 6, 11, 3, 0, 9, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{6, 11, 3, 1, 5, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{5, 9, 0, 2, 6, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 5, 6, 2, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{5, 6, 10, -1, -1, -1, -1, -1}}, {{7, 5, 10, 11, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{11, 7, 5, 1, 2, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{10, 5, 7, 3, 2, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 1, 5, 7, -1, -1, -1, -1}}, {{0, 8, 7, 5, 1, -1, -1, -1}}, {{0, 9, 5, 7, 3, -1, -1, -1}}, {{7, 5, 9, 8, -1, -1, -1, -1}}, {{4, 8, 11, 10, 5, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 5, 10, 2, 3, 8, -1, -1}}, {{5, 10, 2, 0, 4, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 8, 3, 1, 5, -1, -1, -1}}, {{0, 4, 5, 1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 5, 9, -1, -1, -1, -1, -1}}, {{7, 11, 10, 9, 4, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 4, 9, 1, 2, 11, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{7, 11, 2, 0, 4, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{4, 9, 1, 3, 7, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{3, 7, 4, 0, -1, -1, -1, -1}}, {{7, 4, 8, -1, -1, -1, -1, -1}}, {{10, 11, 8, 9, -1, -1, -1, -1}}, {{0, 3, 11, 10, 9, -1, -1, -1}}, {{1, 0, 8, 11, 10, -1, -1, -1}}, {{1, 3, 11, 10, -1, -1, -1, -1}}, {{2, 1, 9, 8, 11, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{2, 0, 8, 11, -1, -1, -1, -1}}, {{2, 3, 11, -1, -1, -1, -1, -1}}, {{3, 2, 10, 9, 8, -1, -1, -1}}, {{0, 2, 10, 9, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}, {{1, 2, 10, -1, -1, -1, -1, -1}}, {{3, 1, 9, 8, -1, -1, -1, -1}}, {{0, 1, 9, -1, -1, -1, -1, -1}}, {{3, 0, 8, -1, -1, -1, -1, -1}}, {{-1, -1, -1, -1, -1, -1, -1, -1}}}; diff --git a/Modules/MapperExt/src/vtkPointSetSlicer.h b/Modules/MapperExt/src/vtkPointSetSlicer.h index 4d2abfbc6c..1382347790 100644 --- a/Modules/MapperExt/src/vtkPointSetSlicer.h +++ b/Modules/MapperExt/src/vtkPointSetSlicer.h @@ -1,121 +1,121 @@ /*=================================================================== 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 _VTKPOINTSETSLICER_H_ #define _VTKPOINTSETSLICER_H_ #include #include "vtkVersion.h" class vtkCutter; class vtkPlane; class vtkPointLocator; class vtkCell; class vtkDataArray; class vtkCellArray; class vtkPointData; class vtkCellData; #include "mitkCommon.h" #include "vtkPolyDataAlgorithm.h" class vtkPointSetSlicer : public vtkPolyDataAlgorithm { public: vtkTypeMacro(vtkPointSetSlicer, vtkPolyDataAlgorithm); void PrintSelf(std::ostream &os, vtkIndent indent) override; // Description: // Construct with user-specified implicit function; initial value of 0.0; and // generating cut scalars turned off. static vtkPointSetSlicer *New(); // Description: // Override GetMTime because we delegate to vtkContourValues and refer to // vtkImplicitFunction. - unsigned long GetMTime() override; + vtkMTimeType GetMTime() override; // Description // Specify the implicit function to perform the cutting. virtual void SetSlicePlane(vtkPlane *); vtkGetObjectMacro(SlicePlane, vtkPlane); // Description: // If this flag is enabled, then the output scalar values will be // interpolated from the implicit function values, and not the input scalar // data. vtkSetMacro(GenerateCutScalars, int); vtkGetMacro(GenerateCutScalars, int); vtkBooleanMacro(GenerateCutScalars, int); // Description: // Specify a spatial locator for merging points. By default, // an instance of vtkMergePoints is used. void SetLocator(vtkPointLocator *locator); vtkGetObjectMacro(Locator, vtkPointLocator); // Description: // Create default locator. Used to create one when none is specified. The // locator is used to merge coincident points. void CreateDefaultLocator(); protected: vtkPointSetSlicer(vtkPlane *cf = 0); ~vtkPointSetSlicer(); virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *) override; virtual int RequestUpdateExtent(vtkInformation *, vtkInformationVector **, vtkInformationVector *) override; virtual int FillInputPortInformation(int port, vtkInformation *info) override; void UnstructuredGridCutter(vtkDataSet *input, vtkPolyData *output); void ContourUnstructuredGridCell(vtkCell *cell, vtkDataArray *cellScalars, vtkPointLocator *locator, vtkCellArray *verts, vtkCellArray *lines, vtkCellArray *polys, vtkPointData *inPd, vtkPointData *outPd, vtkCellData *inCd, vtkIdType cellId, vtkCellData *outCd); vtkPlane *SlicePlane; vtkCutter *Cutter; vtkPointLocator *Locator; int GenerateCutScalars; private: vtkPointSetSlicer(const vtkPointSetSlicer &); // Not implemented. void operator=(const vtkPointSetSlicer &); // Not implemented. static int edges[12][2]; typedef int EDGE_LIST; typedef struct { EDGE_LIST edges[8]; } POLY_CASES; static POLY_CASES polyCases[256]; }; #endif /* _VTKPOINTSETSLICER_H_ */ diff --git a/Modules/MapperExt/src/vtkUnstructuredGridMapper.cpp b/Modules/MapperExt/src/vtkUnstructuredGridMapper.cpp index c8ba584b54..27fff10ce5 100644 --- a/Modules/MapperExt/src/vtkUnstructuredGridMapper.cpp +++ b/Modules/MapperExt/src/vtkUnstructuredGridMapper.cpp @@ -1,223 +1,223 @@ /*=================================================================== 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 "vtkUnstructuredGridMapper.h" #include "vtkExecutive.h" #include "vtkGarbageCollector.h" #include "vtkGeometryFilter.h" #include "vtkInformation.h" #include "vtkObjectFactory.h" #include "vtkPolyData.h" #include "vtkPolyDataMapper.h" #include "vtkScalarsToColors.h" #include "vtkUnstructuredGrid.h" vtkStandardNewMacro(vtkUnstructuredGridMapper); //---------------------------------------------------------------------------- vtkUnstructuredGridMapper::vtkUnstructuredGridMapper() { this->GeometryExtractor = 0; this->PolyDataMapper = 0; } //---------------------------------------------------------------------------- vtkUnstructuredGridMapper::~vtkUnstructuredGridMapper() { // delete internally created objects. if (this->GeometryExtractor) { this->GeometryExtractor->Delete(); } if (this->PolyDataMapper) { this->PolyDataMapper->Delete(); } } void vtkUnstructuredGridMapper::SetBoundingObject(mitk::BoundingObject *bo) { m_BoundingObject = bo; } //---------------------------------------------------------------------------- void vtkUnstructuredGridMapper::SetInput(vtkUnstructuredGrid *input) { this->SetInputDataObject(input); } //---------------------------------------------------------------------------- vtkUnstructuredGrid *vtkUnstructuredGridMapper::GetInput() { // return this->Superclass::GetInputAsDataSet(); return vtkUnstructuredGrid::SafeDownCast(this->GetExecutive()->GetInputData(0, 0)); } //---------------------------------------------------------------------------- void vtkUnstructuredGridMapper::ReleaseGraphicsResources(vtkWindow *renWin) { if (this->PolyDataMapper) { this->PolyDataMapper->ReleaseGraphicsResources(renWin); } } //---------------------------------------------------------------------------- void vtkUnstructuredGridMapper::ReleaseGraphicsResources(mitk::BaseRenderer *renderer) { if (this->PolyDataMapper) { this->PolyDataMapper->ReleaseGraphicsResources(renderer->GetVtkRenderer()->GetRenderWindow()); } } //---------------------------------------------------------------------------- // Receives from Actor -> maps data to primitives // void vtkUnstructuredGridMapper::Render(vtkRenderer *ren, vtkActor *act) { // make sure that we've been properly initialized // if (!this->GetInput()) { vtkErrorMacro(<< "No input!\n"); return; } // Need a lookup table // if (this->LookupTable == 0) { this->CreateDefaultLookupTable(); } this->LookupTable->Build(); // Now can create appropriate mapper // if (this->PolyDataMapper == 0) { vtkGeometryFilter *gf = vtkGeometryFilter::New(); vtkPolyDataMapper *pm = vtkPolyDataMapper::New(); pm->SetInputConnection(gf->GetOutputPort()); this->GeometryExtractor = gf; this->PolyDataMapper = pm; } // share clipping planes with the PolyDataMapper // if (this->ClippingPlanes != this->PolyDataMapper->GetClippingPlanes()) { this->PolyDataMapper->SetClippingPlanes(this->ClippingPlanes); } if (this->m_BoundingObject) { mitk::BoundingBox::BoundsArrayType bounds = this->m_BoundingObject->GetGeometry()->CalculateBoundingBoxRelativeToTransform(0)->GetBounds(); this->GeometryExtractor->SetExtent(bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]); this->GeometryExtractor->ExtentClippingOn(); } else { this->GeometryExtractor->ExtentClippingOff(); } this->GeometryExtractor->SetInputData(this->GetInput()); this->PolyDataMapper->SetInputConnection(this->GeometryExtractor->GetOutputPort()); // update ourselves in case something has changed this->PolyDataMapper->SetLookupTable(this->GetLookupTable()); this->PolyDataMapper->SetScalarVisibility(this->GetScalarVisibility()); this->PolyDataMapper->SetUseLookupTableScalarRange(this->GetUseLookupTableScalarRange()); this->PolyDataMapper->SetScalarRange(this->GetScalarRange()); this->PolyDataMapper->SetImmediateModeRendering(this->GetImmediateModeRendering()); this->PolyDataMapper->SetColorMode(this->GetColorMode()); this->PolyDataMapper->SetInterpolateScalarsBeforeMapping(this->GetInterpolateScalarsBeforeMapping()); this->PolyDataMapper->SetScalarMode(this->GetScalarMode()); if (this->ScalarMode == VTK_SCALAR_MODE_USE_POINT_FIELD_DATA || this->ScalarMode == VTK_SCALAR_MODE_USE_CELL_FIELD_DATA) { if (this->ArrayAccessMode == VTK_GET_ARRAY_BY_ID) { this->PolyDataMapper->ColorByArrayComponent(this->ArrayId, ArrayComponent); } else { this->PolyDataMapper->ColorByArrayComponent(this->ArrayName, ArrayComponent); } } this->PolyDataMapper->Render(ren, act); this->TimeToDraw = this->PolyDataMapper->GetTimeToDraw(); } //---------------------------------------------------------------------------- void vtkUnstructuredGridMapper::PrintSelf(ostream &os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); if (this->PolyDataMapper) { os << indent << "Poly Mapper: (" << this->PolyDataMapper << ")\n"; } else { os << indent << "Poly Mapper: (none)\n"; } if (this->GeometryExtractor) { os << indent << "Geometry Extractor: (" << this->GeometryExtractor << ")\n"; } else { os << indent << "Geometry Extractor: (none)\n"; } } //---------------------------------------------------------------------------- -unsigned long vtkUnstructuredGridMapper::GetMTime() +vtkMTimeType vtkUnstructuredGridMapper::GetMTime() { - unsigned long mTime = this->vtkMapper::GetMTime(); - unsigned long time; + vtkMTimeType mTime = this->vtkMapper::GetMTime(); + vtkMTimeType time; if (this->LookupTable != nullptr) { time = this->LookupTable->GetMTime(); mTime = (time > mTime ? time : mTime); } return mTime; } //---------------------------------------------------------------------------- int vtkUnstructuredGridMapper::FillInputPortInformation(int vtkNotUsed(port), vtkInformation *info) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkUnstructuredGrid"); return 1; } //---------------------------------------------------------------------------- void vtkUnstructuredGridMapper::ReportReferences(vtkGarbageCollector *collector) { this->Superclass::ReportReferences(collector); // These filters share our input and are therefore involved in a // reference loop. vtkGarbageCollectorReport(collector, this->GeometryExtractor, "GeometryExtractor"); vtkGarbageCollectorReport(collector, this->PolyDataMapper, "PolyDataMapper"); } diff --git a/Modules/ModuleList.cmake b/Modules/ModuleList.cmake index 0efaed9db9..b46f1c7326 100644 --- a/Modules/ModuleList.cmake +++ b/Modules/ModuleList.cmake @@ -1,80 +1,78 @@ # The entries in the mitk_modules list must be # ordered according to their dependencies. set(mitk_modules Core CommandLine AppUtil DCMTesting RDF LegacyIO DataTypesExt Annotation LegacyGL AlgorithmsExt MapperExt DICOMReader DICOMReaderServices DICOMTesting SceneSerializationBase PlanarFigure ImageDenoising ImageExtraction SceneSerialization Gizmo GraphAlgorithms Multilabel ImageStatistics ContourModel SurfaceInterpolation Segmentation PlanarFigureSegmentation - OpenViewCore QtWidgets QtWidgetsExt C3js QmlItems SegmentationUI Classification DiffusionImaging GPGPU OpenIGTLink IGTBase IGT CameraCalibration OpenCL OpenCVVideoSupport QtOverlays ToFHardware ToFProcessing ToFUI US USUI DicomUI Simulation Remeshing Python QtPython Persistence OpenIGTLinkUI IGTUI - VtkShaders DicomRT RTUI IOExt XNAT TubeGraph BiophotonicsHardware TumorInvasionAnalysis MatchPointRegistration MatchPointRegistrationUI BoundingShape RenderWindowManager RenderWindowManagerUI CEST DICOMQI ) if(MITK_ENABLE_PIC_READER) list(APPEND mitk_modules IpPicSupportIO) endif() diff --git a/Modules/OpenViewCore/QVTKQuickItem.cxx b/Modules/OpenViewCore/QVTKQuickItem.cxx new file mode 100644 index 0000000000..d08007fdce --- /dev/null +++ b/Modules/OpenViewCore/QVTKQuickItem.cxx @@ -0,0 +1,374 @@ +/*======================================================================== + OpenView -- http://openview.kitware.com + + Copyright 2012 Kitware, Inc. + + Licensed under the BSD license. See LICENSE file for details. + ========================================================================*/ +#include "QVTKQuickItem.h" +#include + +#include +#include +#include +#include +#include +#include + +#include "QVTKInteractor.h" +#include "QVTKInteractorAdapter.h" +#include "vtkGenericOpenGLRenderWindow.h" +#include "vtkEventQtSlotConnect.h" +#include "vtkRenderer.h" +#include "vtkRendererCollection.h" + +#include "vtkCubeSource.h" +#include "vtkPolyDataMapper.h" +#include "vtkProperty.h" + +#include + +QVTKQuickItem::QVTKQuickItem(QQuickItem* parent) +:QQuickItem(parent) +,m_InitCalledOnce(false) +{ + setFlag(ItemHasContents); + setAcceptHoverEvents(true); + setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton); + + m_interactor = vtkSmartPointer::New(); + m_interactorAdapter = new QVTKInteractorAdapter(NULL); + m_interactorAdapter->moveToThread(this->thread()); + m_interactorAdapter->setParent(this); + m_connect = vtkSmartPointer::New(); + //m_connect->Connect(m_interactor, vtkCommand::RenderEvent, this, SLOT(paint())); + vtkSmartPointer win = vtkSmartPointer::New(); + this->SetRenderWindow(win); + this->geometryChanged(QRectF(x(), y(), width(), height()), QRectF(0, 0, 100, 100)); +} + +QVTKQuickItem::~QVTKQuickItem() +{ + this->SetRenderWindow(0); +} + +void QVTKQuickItem::SetRenderWindow(vtkGenericOpenGLRenderWindow* win) +{ + if(m_win) + { + m_win->SetMapped(0); + //m_connect->Disconnect(m_win, vtkCommand::StartEvent, this, SLOT(Start())); + //m_connect->Disconnect(m_win, vtkCommand::WindowMakeCurrentEvent, this, SLOT(MakeCurrent())); + //m_connect->Disconnect(m_win, vtkCommand::EndEvent, this, SLOT(End())); + //m_connect->Disconnect(m_win, vtkCommand::WindowFrameEvent, this, SLOT(Update())); + m_connect->Disconnect(m_win, vtkCommand::WindowIsCurrentEvent, this, SLOT(IsCurrent(vtkObject*, unsigned long, void*, void*))); + m_connect->Disconnect(m_win, vtkCommand::WindowIsDirectEvent, this, SLOT(IsDirect(vtkObject*, unsigned long, void*, void*))); + m_connect->Disconnect(m_win, vtkCommand::WindowSupportsOpenGLEvent, this, SLOT(SupportsOpenGL(vtkObject*, unsigned long, void*, void*))); + } + + m_interactor->SetRenderWindow(win); + m_win = win; + m_interactor->Initialize(); + + if(m_win) + { + m_win->SetMapped(1); + m_win->SetDoubleBuffer(0); + m_win->SetFrontBuffer(COLOR_ATTACHMENT0_EXT); + m_win->SetFrontLeftBuffer(vtkgl::COLOR_ATTACHMENT0_EXT); + m_win->SetBackBuffer(vtkgl::COLOR_ATTACHMENT0_EXT); + m_win->SetBackLeftBuffer(vtkgl::COLOR_ATTACHMENT0_EXT); + + //m_connect->Connect(m_win, vtkCommand::StartEvent, this, SLOT(Start())); + //m_connect->Connect(m_win, vtkCommand::WindowMakeCurrentEvent, this, SLOT(MakeCurrent())); + //m_connect->Connect(m_win, vtkCommand::EndEvent, this, SLOT(End())); + //m_connect->Connect(m_win, vtkCommand::WindowFrameEvent, this, SLOT(Update())); + // Qt::DirectConnection in order to execute callback immediately. + // This avoids an error when vtkTexture attempts to query driver features and it is unable to determine "IsCurrent" + m_connect->Connect(m_win, vtkCommand::WindowIsCurrentEvent, this, SLOT(IsCurrent(vtkObject*, unsigned long, void*, void*)), NULL, 0.0, Qt::DirectConnection); + m_connect->Connect(m_win, vtkCommand::WindowIsDirectEvent, this, SLOT(IsDirect(vtkObject*, unsigned long, void*, void*)), NULL, 0.0, Qt::DirectConnection); + m_connect->Connect(m_win, vtkCommand::WindowSupportsOpenGLEvent, this, SLOT(SupportsOpenGL(vtkObject*, unsigned long, void*, void*)), NULL, 0.0, Qt::DirectConnection); + } +} + +vtkGenericOpenGLRenderWindow* QVTKQuickItem::GetRenderWindow() const +{ + return m_win; +} + +QVTKInteractor* QVTKQuickItem::GetInteractor() const +{ + return m_interactor; +} + +void QVTKQuickItem::itemChange(ItemChange change, const ItemChangeData &) +{ + // The ItemSceneChange event is sent when we are first attached to a canvas. + if (change == ItemSceneChange) { + QQuickWindow *c = window(); + if (!c) + { + return; + } + + // Connect our the beforeRendering signal to our paint function. + // Since this call is executed on the rendering thread it must be + // a Qt::DirectConnection + connect(c, SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection); + + // If we allow QML to do the clearing, they would clear what we paint + // and nothing would show. + c->setClearBeforeRendering(false); + } +} + +void QVTKQuickItem::MakeCurrent() +{ + if (!this->window()) + { + m_win->SetAbortRender(1); + cerr << "Could not make current since there is no canvas!" << endl; + return; + } + if (QThread::currentThread() != this->window()->openglContext()->thread()) + { + m_win->SetAbortRender(1); + cerr << "Could not make current since we are on the wrong thread!" << endl; + return; + } + this->window()->openglContext()->makeCurrent(this->window()); +} + +void QVTKQuickItem::Start() +{ + MakeCurrent(); + + if (!m_win->GetAbortRender()) + { + m_win->PushState(); + m_win->OpenGLInitState(); + } +} + +void QVTKQuickItem::End() +{ + if (!m_win->GetAbortRender()) + { + m_win->PopState(); + } + +} + +void QVTKQuickItem::IsCurrent(vtkObject*, unsigned long, void*, void* call_data) +{ + bool* ptr = reinterpret_cast(call_data); + *ptr = QOpenGLContext::currentContext() == this->window()->openglContext(); +} + +void QVTKQuickItem::IsDirect(vtkObject*, unsigned long, void*, void* call_data) +{ + int* ptr = reinterpret_cast(call_data); + *ptr = 1; +} + +void QVTKQuickItem::SupportsOpenGL(vtkObject*, unsigned long, void*, void* call_data) +{ + int* ptr = reinterpret_cast(call_data); + *ptr = true; + //*ptr = QGLFormat::hasOpenGL(); +} + +void QVTKQuickItem::geometryChanged(const QRectF & newGeometry, const QRectF & oldGeometry) +{ + QQuickItem::geometryChanged(newGeometry, oldGeometry); + QSize oldSize(oldGeometry.width(), oldGeometry.height()); + QSize newSize(newGeometry.width(), newGeometry.height()); + QResizeEvent e(newSize, oldSize); + if (m_interactorAdapter) + { + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(&e, m_interactor); + this->m_viewLock.unlock(); + } + if(m_win.GetPointer() && window()) + { + this->m_viewLock.lock(); + m_win->SetSize(window()->width(), window()->height()); + QPointF origin = mapToScene(QPointF(0, 0)); + QPointF minPt(origin.x()/window()->width(), (window()->height() - origin.y() - height())/window()->height()); + QPointF maxPt(minPt.x() + width()/window()->width(), minPt.y() + height()/window()->height()); + if (m_win->GetRenderers()->GetFirstRenderer()) + { + m_win->GetRenderers()->GetFirstRenderer()->SetViewport(minPt.x(), minPt.y(), maxPt.x(), maxPt.y()); + } + this->m_viewLock.unlock(); + update(); + } +} + +void QVTKQuickItem::keyPressEvent(QKeyEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::keyReleaseEvent(QKeyEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::mousePressEvent(QMouseEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::mouseReleaseEvent(QMouseEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::mouseDoubleClickEvent(QMouseEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::mouseMoveEvent(QMouseEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::wheelEvent(QWheelEvent* e) +{ + e->accept(); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(e, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::hoverEnterEvent(QHoverEvent* e) +{ + e->accept(); + QEvent e2(QEvent::Enter); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(&e2, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::hoverLeaveEvent(QHoverEvent* e) +{ + e->accept(); + QEvent e2(QEvent::Leave); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(&e2, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::hoverMoveEvent(QHoverEvent* e) +{ + e->accept(); + QMouseEvent e2(QEvent::MouseMove, e->pos(), Qt::NoButton, Qt::NoButton, e->modifiers()); + this->m_viewLock.lock(); + m_interactorAdapter->ProcessEvent(&e2, m_interactor); + this->m_viewLock.unlock(); + update(); +} + +void QVTKQuickItem::init() +{ +} + +void QVTKQuickItem::prepareForRender() +{ +} + +void QVTKQuickItem::cleanupAfterRender() +{ +} + +QSGNode* QVTKQuickItem::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) +{ + QSGSimpleRectNode *n = static_cast(oldNode); + if (!n) { + n = new QSGSimpleRectNode(); + } + n->markDirty(QSGNode::DirtyForceUpdate); + return n; +} + + +void QVTKQuickItem::paint() +{ + if (!this->isVisible()) + { + return; + } + + if (!this->m_InitCalledOnce) + { + m_win->GetExtensionManager()->LoadExtension("GL_VERSION_1_4"); + m_win->GetExtensionManager()->LoadExtension("GL_VERSION_2_0"); + + init(); + + this->m_InitCalledOnce = true; + } + + this->m_viewLock.lock(); + + // Let subclasses do something each render + prepareForRender(); + + // Make sure viewport is up to date. + // This is needed because geometryChanged() is not called when parent geometry changes, so we miss when widths/heights + // of surrounding elements change. + m_win->SetSize(window()->width(), window()->height()); + QPointF origin = mapToScene(QPointF(0, 0)); + QPointF minPt(origin.x()/window()->width(), (window()->height() - origin.y() - height())/window()->height()); + QPointF maxPt(minPt.x() + width()/window()->width(), minPt.y() + height()/window()->height()); + if (m_win->GetRenderers()->GetFirstRenderer()) + { + m_win->GetRenderers()->GetFirstRenderer()->SetViewport(minPt.x(), minPt.y(), maxPt.x(), maxPt.y()); + } + + // Turn off any QML shader program + vtkgl::UseProgram(0); + + // Set blending correctly + glEnable(GL_BLEND); + vtkgl::BlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + m_win->Render(); + + // Disable alpha test for QML + glDisable(GL_ALPHA_TEST); + + cleanupAfterRender(); + + this->m_viewLock.unlock(); +} diff --git a/Modules/OpenViewCore/src/QVTKFramebufferObjectRenderer.cxx b/Modules/OpenViewCore/src/QVTKFramebufferObjectRenderer.cxx index 0129eec775..664ae6dc0f 100644 --- a/Modules/OpenViewCore/src/QVTKFramebufferObjectRenderer.cxx +++ b/Modules/OpenViewCore/src/QVTKFramebufferObjectRenderer.cxx @@ -1,98 +1,94 @@ /*=================================================================== 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 "vtkInternalOpenGLRenderWindow.h" #include "QVTKFramebufferObjectRenderer.h" -#include - -#include - #include #include #include #include #include #include #include #include #include #include #include #include #include QVTKFramebufferObjectRenderer::QVTKFramebufferObjectRenderer(vtkInternalOpenGLRenderWindow *rw) : m_vtkRenderWindow(rw), m_neverRendered(true), m_readyToRender(false) { m_vtkRenderWindow->Register(NULL); m_vtkRenderWindow->QtParentRenderer = this; } QOpenGLFramebufferObject* QVTKFramebufferObjectRenderer::createFramebufferObject(const QSize &size) { QOpenGLFramebufferObjectFormat format; format.setAttachment(QOpenGLFramebufferObject::Depth); format.setTextureTarget(GL_TEXTURE_2D); format.setInternalTextureFormat(GL_RGBA32F_ARB); QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(size, format); m_vtkRenderWindow->SetFramebufferObject(fbo); return fbo; } void QVTKFramebufferObjectRenderer::render() { if (!m_readyToRender) { return; } // Ask VTK to render to OpenGL m_vtkQuickItem->m_viewLock.lock(); m_vtkRenderWindow->PushState(); m_vtkRenderWindow->OpenGLInitState(); m_vtkRenderWindow->InternalRender(); m_vtkRenderWindow->OpenGLEndState(); m_vtkRenderWindow->PopState(); m_vtkQuickItem->m_viewLock.unlock(); } void QVTKFramebufferObjectRenderer::synchronize(QQuickFramebufferObject * item) { m_vtkQuickItem = static_cast(item); if (m_neverRendered) { m_neverRendered = false; m_vtkQuickItem->init(); } // Execute events (that might call VTK picking to obtain z coordinates) // while UI and rendering are synchronized. m_vtkQuickItem->processPendingEvents(); // Update MITK mapper list, then mapper outputs m_readyToRender = m_vtkQuickItem->prepareForRender(); } QVTKFramebufferObjectRenderer::~QVTKFramebufferObjectRenderer() { m_vtkRenderWindow->QtParentRenderer = 0; m_vtkRenderWindow->Delete(); } diff --git a/Modules/OpenViewCore/src/QVTKQuickItem.cxx b/Modules/OpenViewCore/src/QVTKQuickItem.cxx index 7862f6bb2e..e2b24d165c 100644 --- a/Modules/OpenViewCore/src/QVTKQuickItem.cxx +++ b/Modules/OpenViewCore/src/QVTKQuickItem.cxx @@ -1,257 +1,255 @@ /*=================================================================== 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. ===================================================================*/ // original copyright below /*======================================================================== OpenView -- http://openview.kitware.com Copyright 2012 Kitware, Inc. Licensed under the BSD license. See LICENSE file for details. ========================================================================*/ #include "QVTKQuickItem.h" #include #include #include #include #include #include "QVTKInteractor.h" #include "QVTKMitkInteractorAdapter.h" #include "vtkGenericOpenGLRenderWindow.h" #include "vtkEventQtSlotConnect.h" -#include "vtkgl.h" -#include "vtkOpenGLExtensionManager.h" #include "vtkRenderer.h" #include "vtkRendererCollection.h" #include "vtkCubeSource.h" #include "vtkPolyDataMapper.h" #include "vtkProperty.h" #include #include "vtkInternalOpenGLRenderWindow.h" #include "QVTKFramebufferObjectRenderer.h" QVTKQuickItem::QVTKQuickItem(QQuickItem* parent) : QQuickFramebufferObject(parent) { setAcceptHoverEvents(true); setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton); m_interactor = vtkSmartPointer::New(); m_interactorAdapter = new QVTKMitkInteractorAdapter(this); m_connect = vtkSmartPointer::New(); m_win = vtkInternalOpenGLRenderWindow::New(); m_interactor->SetRenderWindow(m_win); m_connect->Connect(m_win, vtkCommand::WindowIsCurrentEvent, this, SLOT(IsCurrent(vtkObject*, unsigned long, void*, void*)), NULL, 0.0, Qt::DirectConnection); m_connect->Connect(m_win, vtkCommand::WindowIsDirectEvent, this, SLOT(IsDirect(vtkObject*, unsigned long, void*, void*)), NULL, 0.0, Qt::DirectConnection); m_connect->Connect(m_win, vtkCommand::WindowSupportsOpenGLEvent, this, SLOT(SupportsOpenGL(vtkObject*, unsigned long, void*, void*)), NULL, 0.0, Qt::DirectConnection); connect(this, SIGNAL(textureFollowsItemSizeChanged(bool)), this, SLOT(onTextureFollowsItemSizeChanged(bool))); } QVTKQuickItem::~QVTKQuickItem() { if(m_win) { m_connect->Disconnect(m_win, vtkCommand::WindowIsCurrentEvent, this, SLOT(IsCurrent(vtkObject*, unsigned long, void*, void*))); m_connect->Disconnect(m_win, vtkCommand::WindowIsDirectEvent, this, SLOT(IsDirect(vtkObject*, unsigned long, void*, void*))); m_connect->Disconnect(m_win, vtkCommand::WindowSupportsOpenGLEvent, this, SLOT(SupportsOpenGL(vtkObject*, unsigned long, void*, void*))); m_win->Delete(); } } QSGNode* QVTKQuickItem::updatePaintNode(QSGNode *node, QQuickItem::UpdatePaintNodeData *nodeData) { node = QQuickFramebufferObject::updatePaintNode(node, nodeData); if ( node != nullptr ) { QSGSimpleTextureNode* texNode = static_cast(node); texNode->setTextureCoordinatesTransform(QSGSimpleTextureNode::MirrorVertically); } return node; } QQuickFramebufferObject::Renderer* QVTKQuickItem::createRenderer() const { return new QVTKFramebufferObjectRenderer(static_cast(m_win)); } vtkOpenGLRenderWindow* QVTKQuickItem::GetRenderWindow() const { return m_win; } QVTKInteractor* QVTKQuickItem::GetInteractor() const { return m_interactor; } void QVTKQuickItem::IsCurrent(vtkObject*, unsigned long, void*, void* call_data) { bool* ptr = reinterpret_cast(call_data); *ptr = QOpenGLContext::currentContext() == this->window()->openglContext(); } void QVTKQuickItem::IsDirect(vtkObject*, unsigned long, void*, void* call_data) { int* ptr = reinterpret_cast(call_data); *ptr = 1; } void QVTKQuickItem::SupportsOpenGL(vtkObject*, unsigned long, void*, void* call_data) { int* ptr = reinterpret_cast(call_data); *ptr = 1; } void QVTKQuickItem::onTextureFollowsItemSizeChanged(bool follows) { if (!follows) { qWarning("QVTKQuickItem: Mouse interaction is not (yet) supported when textureFollowsItemSize==false"); } } void QVTKQuickItem::geometryChanged(const QRectF & newGeometry, const QRectF & oldGeometry) { QQuickFramebufferObject::geometryChanged(newGeometry, oldGeometry); QSize oldSize(oldGeometry.width(), oldGeometry.height()); QSize newSize(newGeometry.width(), newGeometry.height()); QResizeEvent e(newSize, oldSize); if (m_interactorAdapter) { this->m_viewLock.lock(); m_interactorAdapter->ProcessEvent(&e, m_interactor); this->m_viewLock.unlock(); } } void QVTKQuickItem::keyPressEvent(QKeyEvent* e) { e->accept(); this->m_viewLock.lock(); m_interactorAdapter->ProcessEvent(e, m_interactor); this->m_viewLock.unlock(); update(); } void QVTKQuickItem::keyReleaseEvent(QKeyEvent* e) { e->accept(); this->m_viewLock.lock(); m_interactorAdapter->ProcessEvent(e, m_interactor); this->m_viewLock.unlock(); update(); } void QVTKQuickItem::mousePressEvent(QMouseEvent* e) { e->accept(); this->m_viewLock.lock(); m_interactorAdapter->ProcessEvent(e, m_interactor); this->m_viewLock.unlock(); update(); } void QVTKQuickItem::mouseReleaseEvent(QMouseEvent* e) { e->accept(); this->m_viewLock.lock(); m_interactorAdapter->ProcessEvent(e, m_interactor); this->m_viewLock.unlock(); update(); } void QVTKQuickItem::mouseDoubleClickEvent(QMouseEvent* e) { e->accept(); this->m_viewLock.lock(); m_interactorAdapter->ProcessEvent(e, m_interactor); this->m_viewLock.unlock(); update(); } void QVTKQuickItem::mouseMoveEvent(QMouseEvent* e) { e->accept(); this->m_viewLock.lock(); m_interactorAdapter->ProcessEvent(e, m_interactor); this->m_viewLock.unlock(); update(); } void QVTKQuickItem::wheelEvent(QWheelEvent* e) { e->accept(); this->m_viewLock.lock(); m_interactorAdapter->ProcessEvent(e, m_interactor); this->m_viewLock.unlock(); update(); } void QVTKQuickItem::hoverEnterEvent(QHoverEvent* e) { e->accept(); QEvent e2(QEvent::Enter); this->m_viewLock.lock(); m_interactorAdapter->ProcessEvent(&e2, m_interactor); this->m_viewLock.unlock(); update(); } void QVTKQuickItem::hoverLeaveEvent(QHoverEvent* e) { e->accept(); QEvent e2(QEvent::Leave); this->m_viewLock.lock(); m_interactorAdapter->ProcessEvent(&e2, m_interactor); this->m_viewLock.unlock(); update(); } void QVTKQuickItem::hoverMoveEvent(QHoverEvent* e) { e->accept(); QMouseEvent e2(QEvent::MouseMove, e->pos(), Qt::NoButton, Qt::NoButton, e->modifiers()); this->m_viewLock.lock(); m_interactorAdapter->ProcessEvent(&e2, m_interactor); this->m_viewLock.unlock(); update(); } void QVTKQuickItem::init() { m_win->OpenGLInitContext(); - m_win->GetExtensionManager()->LoadExtension("GL_VERSION_1_4"); - m_win->GetExtensionManager()->LoadExtension("GL_VERSION_2_0"); +// m_win->GetExtensionManager()->LoadExtension("GL_VERSION_1_4"); +// m_win->GetExtensionManager()->LoadExtension("GL_VERSION_2_0"); } bool QVTKQuickItem::prepareForRender() { return true; } void QVTKQuickItem::cleanupAfterRender() { } diff --git a/Modules/OpenViewCore/src/vtkInternalOpenGLRenderWindow.cxx b/Modules/OpenViewCore/src/vtkInternalOpenGLRenderWindow.cxx index 39e0a384d7..8743363367 100644 --- a/Modules/OpenViewCore/src/vtkInternalOpenGLRenderWindow.cxx +++ b/Modules/OpenViewCore/src/vtkInternalOpenGLRenderWindow.cxx @@ -1,83 +1,80 @@ /*=================================================================== 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 "vtkInternalOpenGLRenderWindow.h" - +#include "vtk_glew.h" +#include "QVTKInternalOpenglRenderWindow.h" #include "QVTKFramebufferObjectRenderer.h" -#include #include vtkStandardNewMacro(vtkInternalOpenGLRenderWindow); vtkInternalOpenGLRenderWindow::~vtkInternalOpenGLRenderWindow() { this->OffScreenRendering = false; } vtkInternalOpenGLRenderWindow::vtkInternalOpenGLRenderWindow() : QtParentRenderer(0) { } void vtkInternalOpenGLRenderWindow::InternalRender() { Superclass::Render(); } void vtkInternalOpenGLRenderWindow::OpenGLEndState() { glDepthMask(GL_TRUE); } void vtkInternalOpenGLRenderWindow::OpenGLInitState() { Superclass::OpenGLInitState(); - vtkgl::UseProgram(0); - +// vtkgl::UseProgram(0); TODO18922 glEnable(GL_BLEND); glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); glDepthMask(GL_TRUE); } void vtkInternalOpenGLRenderWindow::Render() { if (this->QtParentRenderer) { this->QtParentRenderer->update(); } } void vtkInternalOpenGLRenderWindow::SetFramebufferObject(QOpenGLFramebufferObject *fbo) { - this->SetFrontBuffer(vtkgl::COLOR_ATTACHMENT0); - // Why all those buffers, too?? - this->SetFrontRightBuffer(vtkgl::COLOR_ATTACHMENT0); - this->SetBackLeftBuffer(vtkgl::COLOR_ATTACHMENT0); - this->SetBackRightBuffer(vtkgl::COLOR_ATTACHMENT0); + this->SetFrontBuffer(GL_COLOR_ATTACHMENT0); + this->SetFrontLeftBuffer(GL_COLOR_ATTACHMENT0); + this->SetBackBuffer(GL_COLOR_ATTACHMENT0); + this->SetBackLeftBuffer(GL_COLOR_ATTACHMENT0); QSize fboSize = fbo->size(); this->SetSize(fboSize.width(), fboSize.height()); this->NumberOfFrameBuffers = 1; this->FrameBufferObject = static_cast(fbo->handle()); this->DepthRenderBufferObject = 0; // static_cast(depthRenderBufferObject); this->TextureObjects[0] = static_cast(fbo->texture()); this->OffScreenRendering = true; this->OffScreenUseFrameBuffer = true; this->Modified(); } diff --git a/Modules/QtWidgets/CMakeLists.txt b/Modules/QtWidgets/CMakeLists.txt index 65a44f75f5..7307928e23 100644 --- a/Modules/QtWidgets/CMakeLists.txt +++ b/Modules/QtWidgets/CMakeLists.txt @@ -1,9 +1,9 @@ MITK_CREATE_MODULE( INCLUDE_DIRS PRIVATE resource # for xpm includes DEPENDS MitkPlanarFigure MitkAnnotation PACKAGE_DEPENDS - PUBLIC ITK|ITKIOImageBase VTK|vtkGUISupportQt+vtkGUISupportQtOpenGL Qt5|Widgets+OpenGL+Core + PUBLIC ITK|ITKIOImageBase VTK|vtkGUISupportQt Qt5|Widgets+OpenGL+Core SUBPROJECTS MITK-CoreUI ) add_subdirectory(test) diff --git a/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp b/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp index 736ce155b8..793b2984f9 100644 --- a/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp +++ b/Modules/QtWidgets/src/QmitkStdMultiWidget.cpp @@ -1,2056 +1,2052 @@ /*=================================================================== 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 #include #include #include #include #include #include #include "mitkImagePixelReadAccessor.h" #include "mitkPixelTypeMultiplex.h" -#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include QmitkStdMultiWidget::QmitkStdMultiWidget(QWidget *parent, Qt::WindowFlags f, mitk::RenderingManager *renderingManager, mitk::BaseRenderer::RenderingMode::Type renderingMode, const QString &name) : QWidget(parent, f), mitkWidget1(nullptr), mitkWidget2(nullptr), mitkWidget3(nullptr), mitkWidget4(nullptr), levelWindowWidget(nullptr), QmitkStdMultiWidgetLayout(nullptr), m_Layout(LAYOUT_DEFAULT), m_PlaneMode(PLANE_MODE_SLICING), m_RenderingManager(renderingManager), m_GradientBackgroundFlag(true), m_TimeNavigationController(nullptr), m_MainSplit(nullptr), m_LayoutSplit(nullptr), m_SubSplit1(nullptr), m_SubSplit2(nullptr), mitkWidget1Container(nullptr), mitkWidget2Container(nullptr), mitkWidget3Container(nullptr), mitkWidget4Container(nullptr), m_PendingCrosshairPositionEvent(false), m_CrosshairNavigationEnabled(false) { /****************************************************** * Use the global RenderingManager if none was specified * ****************************************************/ if (m_RenderingManager == nullptr) { m_RenderingManager = mitk::RenderingManager::GetInstance(); } m_TimeNavigationController = m_RenderingManager->GetTimeNavigationController(); /*******************************/ // Create Widget manually /*******************************/ // create Layouts QmitkStdMultiWidgetLayout = new QHBoxLayout(this); QmitkStdMultiWidgetLayout->setContentsMargins(0, 0, 0, 0); // Set Layout to widget this->setLayout(QmitkStdMultiWidgetLayout); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // create m_LayoutSplit and add to the mainSplit m_LayoutSplit = new QSplitter(Qt::Vertical, m_MainSplit); m_MainSplit->addWidget(m_LayoutSplit); // create m_SubSplit1 and m_SubSplit2 m_SubSplit1 = new QSplitter(m_LayoutSplit); m_SubSplit2 = new QSplitter(m_LayoutSplit); // creae Widget Container mitkWidget1Container = new QWidget(m_SubSplit1); mitkWidget2Container = new QWidget(m_SubSplit1); mitkWidget3Container = new QWidget(m_SubSplit2); mitkWidget4Container = new QWidget(m_SubSplit2); mitkWidget1Container->setContentsMargins(0, 0, 0, 0); mitkWidget2Container->setContentsMargins(0, 0, 0, 0); mitkWidget3Container->setContentsMargins(0, 0, 0, 0); mitkWidget4Container->setContentsMargins(0, 0, 0, 0); // create Widget Layout QHBoxLayout *mitkWidgetLayout1 = new QHBoxLayout(mitkWidget1Container); QHBoxLayout *mitkWidgetLayout2 = new QHBoxLayout(mitkWidget2Container); QHBoxLayout *mitkWidgetLayout3 = new QHBoxLayout(mitkWidget3Container); QHBoxLayout *mitkWidgetLayout4 = new QHBoxLayout(mitkWidget4Container); m_CornerAnnotations[0] = vtkSmartPointer::New(); m_CornerAnnotations[1] = vtkSmartPointer::New(); m_CornerAnnotations[2] = vtkSmartPointer::New(); m_CornerAnnotations[3] = vtkSmartPointer::New(); m_RectangleProps[0] = vtkSmartPointer::New(); m_RectangleProps[1] = vtkSmartPointer::New(); m_RectangleProps[2] = vtkSmartPointer::New(); m_RectangleProps[3] = vtkSmartPointer::New(); mitkWidgetLayout1->setMargin(0); mitkWidgetLayout2->setMargin(0); mitkWidgetLayout3->setMargin(0); mitkWidgetLayout4->setMargin(0); // set Layout to Widget Container mitkWidget1Container->setLayout(mitkWidgetLayout1); mitkWidget2Container->setLayout(mitkWidgetLayout2); mitkWidget3Container->setLayout(mitkWidgetLayout3); mitkWidget4Container->setLayout(mitkWidgetLayout4); // set SizePolicy mitkWidget1Container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mitkWidget2Container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mitkWidget3Container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); mitkWidget4Container->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // insert Widget Container into the splitters m_SubSplit1->addWidget(mitkWidget1Container); m_SubSplit1->addWidget(mitkWidget2Container); m_SubSplit2->addWidget(mitkWidget3Container); m_SubSplit2->addWidget(mitkWidget4Container); // Create RenderWindows 1 mitkWidget1 = new QmitkRenderWindow(mitkWidget1Container, name + ".widget1", nullptr, m_RenderingManager, renderingMode); mitkWidget1->SetLayoutIndex(AXIAL); mitkWidgetLayout1->addWidget(mitkWidget1); // Create RenderWindows 2 mitkWidget2 = new QmitkRenderWindow(mitkWidget2Container, name + ".widget2", nullptr, m_RenderingManager, renderingMode); mitkWidget2->setEnabled(true); mitkWidget2->SetLayoutIndex(SAGITTAL); mitkWidgetLayout2->addWidget(mitkWidget2); // Create RenderWindows 3 mitkWidget3 = new QmitkRenderWindow(mitkWidget3Container, name + ".widget3", nullptr, m_RenderingManager, renderingMode); mitkWidget3->SetLayoutIndex(CORONAL); mitkWidgetLayout3->addWidget(mitkWidget3); // Create RenderWindows 4 mitkWidget4 = new QmitkRenderWindow(mitkWidget4Container, name + ".widget4", nullptr, m_RenderingManager, renderingMode); mitkWidget4->SetLayoutIndex(THREE_D); mitkWidgetLayout4->addWidget(mitkWidget4); // create SignalSlot Connection connect(mitkWidget1, SIGNAL(SignalLayoutDesignChanged(int)), this, SLOT(OnLayoutDesignChanged(int))); connect(mitkWidget1, SIGNAL(ResetView()), this, SLOT(ResetCrosshair())); connect(mitkWidget1, SIGNAL(ChangeCrosshairRotationMode(int)), this, SLOT(SetWidgetPlaneMode(int))); connect(this, SIGNAL(WidgetNotifyNewCrossHairMode(int)), mitkWidget1, SLOT(OnWidgetPlaneModeChanged(int))); connect(mitkWidget2, SIGNAL(SignalLayoutDesignChanged(int)), this, SLOT(OnLayoutDesignChanged(int))); connect(mitkWidget2, SIGNAL(ResetView()), this, SLOT(ResetCrosshair())); connect(mitkWidget2, SIGNAL(ChangeCrosshairRotationMode(int)), this, SLOT(SetWidgetPlaneMode(int))); connect(this, SIGNAL(WidgetNotifyNewCrossHairMode(int)), mitkWidget2, SLOT(OnWidgetPlaneModeChanged(int))); connect(mitkWidget3, SIGNAL(SignalLayoutDesignChanged(int)), this, SLOT(OnLayoutDesignChanged(int))); connect(mitkWidget3, SIGNAL(ResetView()), this, SLOT(ResetCrosshair())); connect(mitkWidget3, SIGNAL(ChangeCrosshairRotationMode(int)), this, SLOT(SetWidgetPlaneMode(int))); connect(this, SIGNAL(WidgetNotifyNewCrossHairMode(int)), mitkWidget3, SLOT(OnWidgetPlaneModeChanged(int))); connect(mitkWidget4, SIGNAL(SignalLayoutDesignChanged(int)), this, SLOT(OnLayoutDesignChanged(int))); connect(mitkWidget4, SIGNAL(ResetView()), this, SLOT(ResetCrosshair())); connect(mitkWidget4, SIGNAL(ChangeCrosshairRotationMode(int)), this, SLOT(SetWidgetPlaneMode(int))); connect(this, SIGNAL(WidgetNotifyNewCrossHairMode(int)), mitkWidget4, SLOT(OnWidgetPlaneModeChanged(int))); // Create Level Window Widget levelWindowWidget = new QmitkLevelWindowWidget(m_MainSplit); // this levelWindowWidget->setObjectName(QString::fromUtf8("levelWindowWidget")); QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); sizePolicy.setHeightForWidth(levelWindowWidget->sizePolicy().hasHeightForWidth()); levelWindowWidget->setSizePolicy(sizePolicy); levelWindowWidget->setMaximumWidth(50); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // show mainSplitt and add to Layout m_MainSplit->show(); // resize Image. this->resize(QSize(364, 477).expandedTo(minimumSizeHint())); // Initialize the widgets. this->InitializeWidget(); // Activate Widget Menu this->ActivateMenuWidget(true); } void QmitkStdMultiWidget::InitializeWidget() { // Make all black and overwrite renderwindow 4 this->FillGradientBackgroundWithBlack(); // This is #191919 in hex float tmp1[3] = {0.098f, 0.098f, 0.098f}; // This is #7F7F7F in hex float tmp2[3] = {0.498f, 0.498f, 0.498f}; m_GradientBackgroundColors[3] = std::make_pair(mitk::Color(tmp1), mitk::Color(tmp2)); // Yellow is default color for widget4 m_DecorationColorWidget4[0] = 1.0f; m_DecorationColorWidget4[1] = 1.0f; m_DecorationColorWidget4[2] = 0.0f; // transfer colors in WorldGeometry-Nodes of the associated Renderer mitk::IntProperty::Pointer layer; // of widget 1 m_PlaneNode1 = mitk::BaseRenderer::GetInstance(mitkWidget1->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(mitkWidget2->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(mitkWidget3->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(mitkWidget4->GetRenderWindow())->GetCurrentWorldPlaneGeometryNode(); layer = mitk::IntProperty::New(1000); m_ParentNodeForGeometryPlanes->SetProperty("layer", layer); mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())->SetMapperID(mitk::BaseRenderer::Standard3D); // Set plane mode (slicing/rotation behavior) to slicing (default) m_PlaneMode = PLANE_MODE_SLICING; // Set default view directions for SNCs mitkWidget1->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); mitkWidget2->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Sagittal); mitkWidget3->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Frontal); mitkWidget4->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Original); SetDecorationProperties("Axial", GetDecorationColor(0), 0); SetDecorationProperties("Sagittal", GetDecorationColor(1), 1); SetDecorationProperties("Coronal", GetDecorationColor(2), 2); SetDecorationProperties("3D", GetDecorationColor(3), 3); // connect to the "time navigation controller": send time via sliceNavigationControllers m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget1->GetSliceNavigationController(), false); m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget2->GetSliceNavigationController(), false); m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget3->GetSliceNavigationController(), false); m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget4->GetSliceNavigationController(), false); mitkWidget1->GetSliceNavigationController()->ConnectGeometrySendEvent( mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())); // reverse connection between sliceNavigationControllers and m_TimeNavigationController mitkWidget1->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); mitkWidget2->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); mitkWidget3->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); // mitkWidget4->GetSliceNavigationController() // ->ConnectGeometryTimeEvent(m_TimeNavigationController, false); m_MouseModeSwitcher = mitk::MouseModeSwitcher::New(); // setup the department logo rendering m_LogoRendering = mitk::LogoAnnotation::New(); mitk::BaseRenderer::Pointer renderer4 = mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow()); m_LogoRendering->SetOpacity(0.5); - mitk::Point2D offset; - offset.Fill(0.03); - m_LogoRendering->SetOffsetVector(offset); m_LogoRendering->SetRelativeSize(0.15); - m_LogoRendering->SetCornerPosition(1); m_LogoRendering->SetLogoImagePath("DefaultLogo"); - mitk::ManualPlacementAnnotationRenderer::AddAnnotation(m_LogoRendering.GetPointer(), renderer4); + mitk::LayoutAnnotationRenderer::AddAnnotation(m_LogoRendering.GetPointer(), renderer4, mitk::LayoutAnnotationRenderer::BottomRight,30,30); } void QmitkStdMultiWidget::FillGradientBackgroundWithBlack() { // We have 4 widgets and ... for (unsigned int i = 0; i < 4; ++i) { float black[3] = {0.0f, 0.0f, 0.0f}; m_GradientBackgroundColors[i] = std::make_pair(mitk::Color(black), mitk::Color(black)); } } std::pair QmitkStdMultiWidget::GetGradientColors(unsigned int widgetNumber) { if (widgetNumber > 3) { MITK_ERROR << "Decoration color for unknown widget!"; float black[3] = {0.0f, 0.0f, 0.0f}; return std::make_pair(mitk::Color(black), mitk::Color(black)); } return m_GradientBackgroundColors[widgetNumber]; } 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 visibitliy. // 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); } } std::string QmitkStdMultiWidget::GetCornerAnnotationText(unsigned int widgetNumber) { if (widgetNumber > 3) { MITK_ERROR << "Decoration color for unknown widget!"; return std::string(""); } return std::string(m_CornerAnnotations[widgetNumber]->GetText(0)); } QmitkStdMultiWidget::~QmitkStdMultiWidget() { DisablePositionTracking(); // DisableNavigationControllerEventListening(); m_TimeNavigationController->Disconnect(mitkWidget1->GetSliceNavigationController()); m_TimeNavigationController->Disconnect(mitkWidget2->GetSliceNavigationController()); m_TimeNavigationController->Disconnect(mitkWidget3->GetSliceNavigationController()); m_TimeNavigationController->Disconnect(mitkWidget4->GetSliceNavigationController()); } void QmitkStdMultiWidget::RemovePlanesFromDataStorage() { if (m_PlaneNode1.IsNotNull() && m_PlaneNode2.IsNotNull() && m_PlaneNode3.IsNotNull() && m_ParentNodeForGeometryPlanes.IsNotNull()) { if (m_DataStorage.IsNotNull()) { m_DataStorage->Remove(m_PlaneNode1); m_DataStorage->Remove(m_PlaneNode2); m_DataStorage->Remove(m_PlaneNode3); m_DataStorage->Remove(m_ParentNodeForGeometryPlanes); } } } void QmitkStdMultiWidget::AddPlanesToDataStorage() { if (m_PlaneNode1.IsNotNull() && m_PlaneNode2.IsNotNull() && m_PlaneNode3.IsNotNull() && m_ParentNodeForGeometryPlanes.IsNotNull()) { if (m_DataStorage.IsNotNull()) { m_DataStorage->Add(m_ParentNodeForGeometryPlanes); m_DataStorage->Add(m_PlaneNode1, m_ParentNodeForGeometryPlanes); m_DataStorage->Add(m_PlaneNode2, m_ParentNodeForGeometryPlanes); m_DataStorage->Add(m_PlaneNode3, m_ParentNodeForGeometryPlanes); } } } void QmitkStdMultiWidget::changeLayoutTo2DImagesUp() { SMW_INFO << "changing layout to 2D images up... " << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // Set Layout to widget this->setLayout(QmitkStdMultiWidgetLayout); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // create m_LayoutSplit and add to the mainSplit m_LayoutSplit = new QSplitter(Qt::Vertical, m_MainSplit); m_MainSplit->addWidget(m_LayoutSplit); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // create m_SubSplit1 and m_SubSplit2 m_SubSplit1 = new QSplitter(m_LayoutSplit); m_SubSplit2 = new QSplitter(m_LayoutSplit); // insert Widget Container into splitter top m_SubSplit1->addWidget(mitkWidget1Container); m_SubSplit1->addWidget(mitkWidget2Container); m_SubSplit1->addWidget(mitkWidget3Container); // set SplitterSize for splitter top QList splitterSize; splitterSize.push_back(1000); splitterSize.push_back(1000); splitterSize.push_back(1000); m_SubSplit1->setSizes(splitterSize); // insert Widget Container into splitter bottom m_SubSplit2->addWidget(mitkWidget4Container); // set SplitterSize for splitter m_LayoutSplit splitterSize.clear(); splitterSize.push_back(400); splitterSize.push_back(1000); m_LayoutSplit->setSizes(splitterSize); // show mainSplitt m_MainSplit->show(); // show Widget if hidden if (mitkWidget1->isHidden()) mitkWidget1->show(); if (mitkWidget2->isHidden()) mitkWidget2->show(); if (mitkWidget3->isHidden()) mitkWidget3->show(); if (mitkWidget4->isHidden()) mitkWidget4->show(); // Change Layout Name m_Layout = LAYOUT_2D_IMAGES_UP; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_2D_IMAGES_UP); mitkWidget2->LayoutDesignListChanged(LAYOUT_2D_IMAGES_UP); mitkWidget3->LayoutDesignListChanged(LAYOUT_2D_IMAGES_UP); mitkWidget4->LayoutDesignListChanged(LAYOUT_2D_IMAGES_UP); // update Alle Widgets this->UpdateAllWidgets(); } void QmitkStdMultiWidget::changeLayoutTo2DImagesLeft() { SMW_INFO << "changing layout to 2D images left... " << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // create m_LayoutSplit and add to the mainSplit m_LayoutSplit = new QSplitter(m_MainSplit); m_MainSplit->addWidget(m_LayoutSplit); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // create m_SubSplit1 and m_SubSplit2 m_SubSplit1 = new QSplitter(Qt::Vertical, m_LayoutSplit); m_SubSplit2 = new QSplitter(m_LayoutSplit); // insert Widget into the splitters m_SubSplit1->addWidget(mitkWidget1Container); m_SubSplit1->addWidget(mitkWidget2Container); m_SubSplit1->addWidget(mitkWidget3Container); // set splitterSize of SubSplit1 QList splitterSize; splitterSize.push_back(1000); splitterSize.push_back(1000); splitterSize.push_back(1000); m_SubSplit1->setSizes(splitterSize); m_SubSplit2->addWidget(mitkWidget4Container); // set splitterSize of Layout Split splitterSize.clear(); splitterSize.push_back(400); splitterSize.push_back(1000); m_LayoutSplit->setSizes(splitterSize); // show mainSplitt and add to Layout m_MainSplit->show(); // show Widget if hidden if (mitkWidget1->isHidden()) mitkWidget1->show(); if (mitkWidget2->isHidden()) mitkWidget2->show(); if (mitkWidget3->isHidden()) mitkWidget3->show(); if (mitkWidget4->isHidden()) mitkWidget4->show(); // update Layout Name m_Layout = LAYOUT_2D_IMAGES_LEFT; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_2D_IMAGES_LEFT); mitkWidget2->LayoutDesignListChanged(LAYOUT_2D_IMAGES_LEFT); mitkWidget3->LayoutDesignListChanged(LAYOUT_2D_IMAGES_LEFT); mitkWidget4->LayoutDesignListChanged(LAYOUT_2D_IMAGES_LEFT); // update Alle Widgets this->UpdateAllWidgets(); } void QmitkStdMultiWidget::SetDecorationProperties(std::string text, mitk::Color color, int widgetNumber) { if (widgetNumber > 3) { MITK_ERROR << "Unknown render window for annotation."; return; } vtkRenderer *renderer = this->GetRenderWindow(widgetNumber)->GetRenderer()->GetVtkRenderer(); if (!renderer) return; vtkSmartPointer annotation = m_CornerAnnotations[widgetNumber]; annotation->SetText(0, text.c_str()); annotation->SetMaximumFontSize(12); annotation->GetTextProperty()->SetColor(color[0], color[1], color[2]); if (!renderer->HasViewProp(annotation)) { renderer->AddViewProp(annotation); } vtkSmartPointer frame = m_RectangleProps[widgetNumber]; frame->SetColor(color[0], color[1], color[2]); if (!renderer->HasViewProp(frame)) { renderer->AddViewProp(frame); } } void QmitkStdMultiWidget::SetCornerAnnotationVisibility(bool visibility) { for (int i = 0; i < 4; ++i) { m_CornerAnnotations[i]->SetVisibility(visibility); } } bool QmitkStdMultiWidget::IsCornerAnnotationVisible(void) const { return m_CornerAnnotations[0]->GetVisibility() > 0; } QmitkRenderWindow *QmitkStdMultiWidget::GetRenderWindow(unsigned int number) { switch (number) { case 0: return this->GetRenderWindow1(); case 1: return this->GetRenderWindow2(); case 2: return this->GetRenderWindow3(); case 3: return this->GetRenderWindow4(); default: MITK_ERROR << "Requested unknown render window"; break; } return nullptr; } void QmitkStdMultiWidget::changeLayoutToDefault() { SMW_INFO << "changing layout to default... " << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // create m_LayoutSplit and add to the mainSplit m_LayoutSplit = new QSplitter(Qt::Vertical, m_MainSplit); m_MainSplit->addWidget(m_LayoutSplit); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // create m_SubSplit1 and m_SubSplit2 m_SubSplit1 = new QSplitter(m_LayoutSplit); m_SubSplit2 = new QSplitter(m_LayoutSplit); // insert Widget container into the splitters m_SubSplit1->addWidget(mitkWidget1Container); m_SubSplit1->addWidget(mitkWidget2Container); m_SubSplit2->addWidget(mitkWidget3Container); m_SubSplit2->addWidget(mitkWidget4Container); // set splitter Size QList splitterSize; splitterSize.push_back(1000); splitterSize.push_back(1000); m_SubSplit1->setSizes(splitterSize); m_SubSplit2->setSizes(splitterSize); m_LayoutSplit->setSizes(splitterSize); // show mainSplitt and add to Layout m_MainSplit->show(); // show Widget if hidden if (mitkWidget1->isHidden()) mitkWidget1->show(); if (mitkWidget2->isHidden()) mitkWidget2->show(); if (mitkWidget3->isHidden()) mitkWidget3->show(); if (mitkWidget4->isHidden()) mitkWidget4->show(); m_Layout = LAYOUT_DEFAULT; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_DEFAULT); mitkWidget2->LayoutDesignListChanged(LAYOUT_DEFAULT); mitkWidget3->LayoutDesignListChanged(LAYOUT_DEFAULT); mitkWidget4->LayoutDesignListChanged(LAYOUT_DEFAULT); // update Alle Widgets this->UpdateAllWidgets(); } void QmitkStdMultiWidget::changeLayoutToBig3D() { SMW_INFO << "changing layout to big 3D ..." << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // add widget Splitter to main Splitter m_MainSplit->addWidget(mitkWidget4Container); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // show mainSplitt and add to Layout m_MainSplit->show(); // show/hide Widgets mitkWidget1->hide(); mitkWidget2->hide(); mitkWidget3->hide(); if (mitkWidget4->isHidden()) mitkWidget4->show(); m_Layout = LAYOUT_BIG_3D; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_BIG_3D); mitkWidget2->LayoutDesignListChanged(LAYOUT_BIG_3D); mitkWidget3->LayoutDesignListChanged(LAYOUT_BIG_3D); mitkWidget4->LayoutDesignListChanged(LAYOUT_BIG_3D); // update Alle Widgets this->UpdateAllWidgets(); mitk::RenderingManager::GetInstance()->SetRenderWindowFocus(mitkWidget4->GetVtkRenderWindow()); } void QmitkStdMultiWidget::changeLayoutToWidget1() { SMW_INFO << "changing layout to big Widget1 ..." << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // add widget Splitter to main Splitter m_MainSplit->addWidget(mitkWidget1Container); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // show mainSplitt and add to Layout m_MainSplit->show(); // show/hide Widgets if (mitkWidget1->isHidden()) mitkWidget1->show(); mitkWidget2->hide(); mitkWidget3->hide(); mitkWidget4->hide(); m_Layout = LAYOUT_WIDGET1; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_WIDGET1); mitkWidget2->LayoutDesignListChanged(LAYOUT_WIDGET1); mitkWidget3->LayoutDesignListChanged(LAYOUT_WIDGET1); mitkWidget4->LayoutDesignListChanged(LAYOUT_WIDGET1); // update Alle Widgets this->UpdateAllWidgets(); mitk::RenderingManager::GetInstance()->SetRenderWindowFocus(mitkWidget1->GetVtkRenderWindow()); } void QmitkStdMultiWidget::changeLayoutToWidget2() { SMW_INFO << "changing layout to big Widget2 ..." << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // add widget Splitter to main Splitter m_MainSplit->addWidget(mitkWidget2Container); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // show mainSplitt and add to Layout m_MainSplit->show(); // show/hide Widgets mitkWidget1->hide(); if (mitkWidget2->isHidden()) mitkWidget2->show(); mitkWidget3->hide(); mitkWidget4->hide(); m_Layout = LAYOUT_WIDGET2; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_WIDGET2); mitkWidget2->LayoutDesignListChanged(LAYOUT_WIDGET2); mitkWidget3->LayoutDesignListChanged(LAYOUT_WIDGET2); mitkWidget4->LayoutDesignListChanged(LAYOUT_WIDGET2); // update Alle Widgets this->UpdateAllWidgets(); mitk::RenderingManager::GetInstance()->SetRenderWindowFocus(mitkWidget2->GetVtkRenderWindow()); } void QmitkStdMultiWidget::changeLayoutToWidget3() { SMW_INFO << "changing layout to big Widget3 ..." << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // add widget Splitter to main Splitter m_MainSplit->addWidget(mitkWidget3Container); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // show mainSplitt and add to Layout m_MainSplit->show(); // show/hide Widgets mitkWidget1->hide(); mitkWidget2->hide(); if (mitkWidget3->isHidden()) mitkWidget3->show(); mitkWidget4->hide(); m_Layout = LAYOUT_WIDGET3; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_WIDGET3); mitkWidget2->LayoutDesignListChanged(LAYOUT_WIDGET3); mitkWidget3->LayoutDesignListChanged(LAYOUT_WIDGET3); mitkWidget4->LayoutDesignListChanged(LAYOUT_WIDGET3); // update Alle Widgets this->UpdateAllWidgets(); mitk::RenderingManager::GetInstance()->SetRenderWindowFocus(mitkWidget3->GetVtkRenderWindow()); } void QmitkStdMultiWidget::changeLayoutToRowWidget3And4() { SMW_INFO << "changing layout to Widget3 and 4 in a Row..." << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // create m_LayoutSplit and add to the mainSplit m_LayoutSplit = new QSplitter(Qt::Vertical, m_MainSplit); m_MainSplit->addWidget(m_LayoutSplit); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // add Widgets to splitter m_LayoutSplit->addWidget(mitkWidget3Container); m_LayoutSplit->addWidget(mitkWidget4Container); // set Splitter Size QList splitterSize; splitterSize.push_back(1000); splitterSize.push_back(1000); m_LayoutSplit->setSizes(splitterSize); // show mainSplitt and add to Layout m_MainSplit->show(); // show/hide Widgets mitkWidget1->hide(); mitkWidget2->hide(); if (mitkWidget3->isHidden()) mitkWidget3->show(); if (mitkWidget4->isHidden()) mitkWidget4->show(); m_Layout = LAYOUT_ROW_WIDGET_3_AND_4; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_ROW_WIDGET_3_AND_4); mitkWidget2->LayoutDesignListChanged(LAYOUT_ROW_WIDGET_3_AND_4); mitkWidget3->LayoutDesignListChanged(LAYOUT_ROW_WIDGET_3_AND_4); mitkWidget4->LayoutDesignListChanged(LAYOUT_ROW_WIDGET_3_AND_4); // update Alle Widgets this->UpdateAllWidgets(); } void QmitkStdMultiWidget::changeLayoutToColumnWidget3And4() { SMW_INFO << "changing layout to Widget3 and 4 in one Column..." << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // create m_LayoutSplit and add to the mainSplit m_LayoutSplit = new QSplitter(m_MainSplit); m_MainSplit->addWidget(m_LayoutSplit); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // add Widgets to splitter m_LayoutSplit->addWidget(mitkWidget3Container); m_LayoutSplit->addWidget(mitkWidget4Container); // set SplitterSize QList splitterSize; splitterSize.push_back(1000); splitterSize.push_back(1000); m_LayoutSplit->setSizes(splitterSize); // show mainSplitt and add to Layout m_MainSplit->show(); // show/hide Widgets mitkWidget1->hide(); mitkWidget2->hide(); if (mitkWidget3->isHidden()) mitkWidget3->show(); if (mitkWidget4->isHidden()) mitkWidget4->show(); m_Layout = LAYOUT_COLUMN_WIDGET_3_AND_4; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_COLUMN_WIDGET_3_AND_4); mitkWidget2->LayoutDesignListChanged(LAYOUT_COLUMN_WIDGET_3_AND_4); mitkWidget3->LayoutDesignListChanged(LAYOUT_COLUMN_WIDGET_3_AND_4); mitkWidget4->LayoutDesignListChanged(LAYOUT_COLUMN_WIDGET_3_AND_4); // update Alle Widgets this->UpdateAllWidgets(); } void QmitkStdMultiWidget::changeLayoutToRowWidgetSmall3andBig4() { SMW_INFO << "changing layout to Widget3 and 4 in a Row..." << std::endl; this->changeLayoutToRowWidget3And4(); m_Layout = LAYOUT_ROW_WIDGET_SMALL3_AND_BIG4; } void QmitkStdMultiWidget::changeLayoutToSmallUpperWidget2Big3and4() { SMW_INFO << "changing layout to Widget3 and 4 in a Row..." << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // create m_LayoutSplit and add to the mainSplit m_LayoutSplit = new QSplitter(Qt::Vertical, m_MainSplit); m_MainSplit->addWidget(m_LayoutSplit); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // create m_SubSplit1 and m_SubSplit2 m_SubSplit1 = new QSplitter(Qt::Vertical, m_LayoutSplit); m_SubSplit2 = new QSplitter(m_LayoutSplit); // insert Widget into the splitters m_SubSplit1->addWidget(mitkWidget2Container); m_SubSplit2->addWidget(mitkWidget3Container); m_SubSplit2->addWidget(mitkWidget4Container); // set Splitter Size QList splitterSize; splitterSize.push_back(1000); splitterSize.push_back(1000); m_SubSplit2->setSizes(splitterSize); splitterSize.clear(); splitterSize.push_back(500); splitterSize.push_back(1000); m_LayoutSplit->setSizes(splitterSize); // show mainSplitt m_MainSplit->show(); // show Widget if hidden mitkWidget1->hide(); if (mitkWidget2->isHidden()) mitkWidget2->show(); if (mitkWidget3->isHidden()) mitkWidget3->show(); if (mitkWidget4->isHidden()) mitkWidget4->show(); m_Layout = LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4); mitkWidget2->LayoutDesignListChanged(LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4); mitkWidget3->LayoutDesignListChanged(LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4); mitkWidget4->LayoutDesignListChanged(LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4); // update Alle Widgets this->UpdateAllWidgets(); } void QmitkStdMultiWidget::changeLayoutTo2x2Dand3DWidget() { SMW_INFO << "changing layout to 2 x 2D and 3D Widget" << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // create m_LayoutSplit and add to the mainSplit m_LayoutSplit = new QSplitter(m_MainSplit); m_MainSplit->addWidget(m_LayoutSplit); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // create m_SubSplit1 and m_SubSplit2 m_SubSplit1 = new QSplitter(Qt::Vertical, m_LayoutSplit); m_SubSplit2 = new QSplitter(m_LayoutSplit); // add Widgets to splitter m_SubSplit1->addWidget(mitkWidget1Container); m_SubSplit1->addWidget(mitkWidget2Container); m_SubSplit2->addWidget(mitkWidget4Container); // set Splitter Size QList splitterSize; splitterSize.push_back(1000); splitterSize.push_back(1000); m_SubSplit1->setSizes(splitterSize); m_LayoutSplit->setSizes(splitterSize); // show mainSplitt and add to Layout m_MainSplit->show(); // show/hide Widgets if (mitkWidget1->isHidden()) mitkWidget1->show(); if (mitkWidget2->isHidden()) mitkWidget2->show(); mitkWidget3->hide(); if (mitkWidget4->isHidden()) mitkWidget4->show(); m_Layout = LAYOUT_2X_2D_AND_3D_WIDGET; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_2X_2D_AND_3D_WIDGET); mitkWidget2->LayoutDesignListChanged(LAYOUT_2X_2D_AND_3D_WIDGET); mitkWidget3->LayoutDesignListChanged(LAYOUT_2X_2D_AND_3D_WIDGET); mitkWidget4->LayoutDesignListChanged(LAYOUT_2X_2D_AND_3D_WIDGET); // update Alle Widgets this->UpdateAllWidgets(); } void QmitkStdMultiWidget::changeLayoutToLeft2Dand3DRight2D() { SMW_INFO << "changing layout to 2D and 3D left, 2D right Widget" << std::endl; // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // create m_LayoutSplit and add to the mainSplit m_LayoutSplit = new QSplitter(m_MainSplit); m_MainSplit->addWidget(m_LayoutSplit); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // create m_SubSplit1 and m_SubSplit2 m_SubSplit1 = new QSplitter(Qt::Vertical, m_LayoutSplit); m_SubSplit2 = new QSplitter(m_LayoutSplit); // add Widgets to splitter m_SubSplit1->addWidget(mitkWidget1Container); m_SubSplit1->addWidget(mitkWidget4Container); m_SubSplit2->addWidget(mitkWidget2Container); // set Splitter Size QList splitterSize; splitterSize.push_back(1000); splitterSize.push_back(1000); m_SubSplit1->setSizes(splitterSize); m_LayoutSplit->setSizes(splitterSize); // show mainSplitt and add to Layout m_MainSplit->show(); // show/hide Widgets if (mitkWidget1->isHidden()) mitkWidget1->show(); if (mitkWidget2->isHidden()) mitkWidget2->show(); mitkWidget3->hide(); if (mitkWidget4->isHidden()) mitkWidget4->show(); m_Layout = LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET); mitkWidget2->LayoutDesignListChanged(LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET); mitkWidget3->LayoutDesignListChanged(LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET); mitkWidget4->LayoutDesignListChanged(LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET); // update Alle Widgets this->UpdateAllWidgets(); } void QmitkStdMultiWidget::changeLayoutTo2DUpAnd3DDown(unsigned int id2Dwindow) { SMW_INFO << "changing layout to 2D up and 3D down" << std::endl; if (id2Dwindow < 1 || id2Dwindow > 3) { MITK_WARN << "Only 2D render window IDs 1,2 or 3 are valid. Got ID " << id2Dwindow << ". " << "Using default ID 2 instead."; id2Dwindow = 2; } // Hide all Menu Widgets this->HideAllWidgetToolbars(); delete QmitkStdMultiWidgetLayout; // create Main Layout QmitkStdMultiWidgetLayout = new QHBoxLayout(this); // Set Layout to widget this->setLayout(QmitkStdMultiWidgetLayout); // create main splitter m_MainSplit = new QSplitter(this); QmitkStdMultiWidgetLayout->addWidget(m_MainSplit); // create m_LayoutSplit and add to the mainSplit m_LayoutSplit = new QSplitter(Qt::Vertical, m_MainSplit); m_MainSplit->addWidget(m_LayoutSplit); // add LevelWindow Widget to mainSplitter m_MainSplit->addWidget(levelWindowWidget); // create m_SubSplit1 and m_SubSplit2 m_SubSplit1 = new QSplitter(m_LayoutSplit); m_SubSplit2 = new QSplitter(m_LayoutSplit); // insert Widget Container into splitter top switch (id2Dwindow) { case 1: m_SubSplit1->addWidget(mitkWidget1Container); break; case 2: m_SubSplit1->addWidget(mitkWidget2Container); break; case 3: m_SubSplit1->addWidget(mitkWidget3Container); break; } // set SplitterSize for splitter top QList splitterSize; // insert Widget Container into splitter bottom m_SubSplit2->addWidget(mitkWidget4Container); // set SplitterSize for splitter m_LayoutSplit splitterSize.clear(); splitterSize.push_back(700); splitterSize.push_back(700); m_LayoutSplit->setSizes(splitterSize); // show mainSplitt m_MainSplit->show(); // show/hide Widgets switch (id2Dwindow) { case 1: if (mitkWidget1->isHidden()) mitkWidget1->show(); mitkWidget2->hide(); mitkWidget3->hide(); break; case 2: if (mitkWidget2->isHidden()) mitkWidget2->show(); mitkWidget1->hide(); mitkWidget3->hide(); break; case 3: if (mitkWidget3->isHidden()) mitkWidget3->show(); mitkWidget1->hide(); mitkWidget2->hide(); break; } //always show 3D widget if (mitkWidget4->isHidden()) mitkWidget4->show(); m_Layout = LAYOUT_2D_UP_AND_3D_DOWN; // update Layout Design List mitkWidget1->LayoutDesignListChanged(LAYOUT_2D_UP_AND_3D_DOWN); mitkWidget2->LayoutDesignListChanged(LAYOUT_2D_UP_AND_3D_DOWN); mitkWidget3->LayoutDesignListChanged(LAYOUT_2D_UP_AND_3D_DOWN); mitkWidget4->LayoutDesignListChanged(LAYOUT_2D_UP_AND_3D_DOWN); // update all Widgets this->UpdateAllWidgets(); } void QmitkStdMultiWidget::SetDataStorage(mitk::DataStorage *ds) { if (ds == m_DataStorage) { return; } mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())->SetDataStorage(ds); mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow())->SetDataStorage(ds); mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow())->SetDataStorage(ds); mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())->SetDataStorage(ds); m_DataStorage = ds; } void QmitkStdMultiWidget::Fit() { vtkSmartPointer vtkrenderer; vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())->GetVtkRenderer(); if (vtkrenderer != nullptr) vtkrenderer->ResetCamera(); vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow())->GetVtkRenderer(); if (vtkrenderer != nullptr) vtkrenderer->ResetCamera(); vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow())->GetVtkRenderer(); if (vtkrenderer != nullptr) vtkrenderer->ResetCamera(); vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())->GetVtkRenderer(); if (vtkrenderer != nullptr) vtkrenderer->ResetCamera(); mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())->GetCameraController()->Fit(); mitk::BaseRenderer::GetInstance(mitkWidget2->GetRenderWindow())->GetCameraController()->Fit(); mitk::BaseRenderer::GetInstance(mitkWidget3->GetRenderWindow())->GetCameraController()->Fit(); mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow())->GetCameraController()->Fit(); int w = vtkObject::GetGlobalWarningDisplay(); vtkObject::GlobalWarningDisplayOff(); vtkObject::SetGlobalWarningDisplay(w); } void QmitkStdMultiWidget::InitPositionTracking() { // TODO POSITIONTRACKER } 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(mitkWidget1->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(mitkWidget2->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(mitkWidget3->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)); } mitk::SliceNavigationController *QmitkStdMultiWidget::GetTimeNavigationController() { return m_TimeNavigationController; } void QmitkStdMultiWidget::EnableStandardLevelWindow() { levelWindowWidget->disconnect(this); levelWindowWidget->SetDataStorage(mitk::BaseRenderer::GetInstance(mitkWidget1->GetRenderWindow())->GetDataStorage()); levelWindowWidget->show(); } void QmitkStdMultiWidget::DisableStandardLevelWindow() { levelWindowWidget->disconnect(this); levelWindowWidget->hide(); } // CAUTION: Legacy code for enabling Qt-signal-controlled view initialization. // Use RenderingManager::InitializeViews() instead. bool QmitkStdMultiWidget::InitializeStandardViews(const mitk::Geometry3D *geometry) { return m_RenderingManager->InitializeViews(geometry); } void QmitkStdMultiWidget::RequestUpdate() { m_RenderingManager->RequestUpdate(mitkWidget1->GetRenderWindow()); m_RenderingManager->RequestUpdate(mitkWidget2->GetRenderWindow()); m_RenderingManager->RequestUpdate(mitkWidget3->GetRenderWindow()); m_RenderingManager->RequestUpdate(mitkWidget4->GetRenderWindow()); } void QmitkStdMultiWidget::ForceImmediateUpdate() { m_RenderingManager->ForceImmediateUpdate(mitkWidget1->GetRenderWindow()); m_RenderingManager->ForceImmediateUpdate(mitkWidget2->GetRenderWindow()); m_RenderingManager->ForceImmediateUpdate(mitkWidget3->GetRenderWindow()); m_RenderingManager->ForceImmediateUpdate(mitkWidget4->GetRenderWindow()); } void QmitkStdMultiWidget::wheelEvent(QWheelEvent *e) { emit WheelMoved(e); } void QmitkStdMultiWidget::mousePressEvent(QMouseEvent *) { } 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(); } QmitkRenderWindow *QmitkStdMultiWidget::GetRenderWindow1() const { return mitkWidget1; } QmitkRenderWindow *QmitkStdMultiWidget::GetRenderWindow2() const { return mitkWidget2; } QmitkRenderWindow *QmitkStdMultiWidget::GetRenderWindow3() const { return mitkWidget3; } QmitkRenderWindow *QmitkStdMultiWidget::GetRenderWindow4() const { return mitkWidget4; } const mitk::Point3D QmitkStdMultiWidget::GetCrossPosition() const { const mitk::PlaneGeometry *plane1 = mitkWidget1->GetSliceNavigationController()->GetCurrentPlaneGeometry(); const mitk::PlaneGeometry *plane2 = mitkWidget2->GetSliceNavigationController()->GetCurrentPlaneGeometry(); const mitk::PlaneGeometry *plane3 = mitkWidget3->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; } } // TODO BUG POSITIONTRACKER; mitk::Point3D p; return p; // return m_LastLeftClickPositionSupplier->GetCurrentPoint(); } void QmitkStdMultiWidget::EnablePositionTracking() { } void QmitkStdMultiWidget::DisablePositionTracking() { } 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::MoveCrossToPosition(const mitk::Point3D &newPosition) { mitkWidget1->GetSliceNavigationController()->SelectSliceByPoint(newPosition); mitkWidget2->GetSliceNavigationController()->SelectSliceByPoint(newPosition); mitkWidget3->GetSliceNavigationController()->SelectSliceByPoint(newPosition); m_RenderingManager->RequestUpdateAll(); } void QmitkStdMultiWidget::HandleCrosshairPositionEvent() { if (!m_PendingCrosshairPositionEvent) { m_PendingCrosshairPositionEvent = true; QTimer::singleShot(0, this, SLOT(HandleCrosshairPositionEventDelayed())); } } mitk::DataNode::Pointer QmitkStdMultiWidget::GetTopLayerNode(mitk::DataStorage::SetOfObjects::ConstPointer nodes) { mitk::Point3D crosshairPos = this->GetCrossPosition(); mitk::DataNode::Pointer node; int maxlayer = -32768; if (nodes.IsNotNull()) { mitk::BaseRenderer *baseRenderer = this->mitkWidget1->GetSliceNavigationController()->GetRenderer(); // find node with largest layer, that is the node shown on top in the render window for (unsigned int x = 0; x < nodes->size(); x++) { if ((nodes->at(x)->GetData()->GetGeometry() != nullptr) && nodes->at(x)->GetData()->GetGeometry()->IsInside(crosshairPos)) { int layer = 0; if (!(nodes->at(x)->GetIntProperty("layer", layer))) continue; if (layer > maxlayer) { if (static_cast(nodes->at(x))->IsVisible(baseRenderer)) { node = nodes->at(x); maxlayer = layer; } } } } } return node; } void QmitkStdMultiWidget::HandleCrosshairPositionEventDelayed() { m_PendingCrosshairPositionEvent = false; // find image with highest layer mitk::TNodePredicateDataType::Pointer isImageData = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer nodes = this->m_DataStorage->GetSubset(isImageData).GetPointer(); mitk::DataNode::Pointer node; mitk::DataNode::Pointer topSourceNode; mitk::Image::Pointer image; bool isBinary = false; node = this->GetTopLayerNode(nodes); int component = 0; if (node.IsNotNull()) { node->GetBoolProperty("binary", isBinary); if (isBinary) { mitk::DataStorage::SetOfObjects::ConstPointer sourcenodes = m_DataStorage->GetSources(node, nullptr, true); if (!sourcenodes->empty()) { topSourceNode = this->GetTopLayerNode(sourcenodes); } 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); } } mitk::Point3D crosshairPos = this->GetCrossPosition(); std::string statusText; std::stringstream stream; itk::Index<3> p; mitk::BaseRenderer *baseRenderer = this->mitkWidget1->GetSliceNavigationController()->GetRenderer(); 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(baseRenderer->GetTimeStep()), p, pixelValue, component); if (fabs(pixelValue) > 1000000 || fabs(pixelValue) < 0.01) { stream << "; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: " << std::scientific << pixelValue << " "; } else { stream << "; Time: " << baseRenderer->GetTime() << " ms; Pixelvalue: " << pixelValue << " "; } } else { stream << "No image information at this position!"; } statusText = stream.str(); mitk::StatusBar::GetInstance()->DisplayGreyValueText(statusText.c_str()); } int QmitkStdMultiWidget::GetLayout() const { return m_Layout; } bool QmitkStdMultiWidget::GetGradientBackgroundFlag() const { return m_GradientBackgroundFlag; } void QmitkStdMultiWidget::EnableGradientBackground() { // gradient background is by default only in widget 4, otherwise // interferences between 2D rendering and VTK rendering may occur. for (unsigned int i = 0; i < 4; ++i) { GetRenderWindow(i)->GetRenderer()->GetVtkRenderer()->GradientBackgroundOn(); } m_GradientBackgroundFlag = true; } void QmitkStdMultiWidget::DisableGradientBackground() { for (unsigned int i = 0; i < 4; ++i) { GetRenderWindow(i)->GetRenderer()->GetVtkRenderer()->GradientBackgroundOff(); } m_GradientBackgroundFlag = false; } void QmitkStdMultiWidget::EnableDepartmentLogo() { m_LogoRendering->SetVisibility(true); RequestUpdate(); } void QmitkStdMultiWidget::DisableDepartmentLogo() { m_LogoRendering->SetVisibility(false); RequestUpdate(); } bool QmitkStdMultiWidget::IsDepartmentLogoEnabled() const { return m_LogoRendering->IsVisible(); } void QmitkStdMultiWidget::SetWidgetPlaneVisibility(const char *widgetName, bool visible, mitk::BaseRenderer *renderer) { if (m_DataStorage.IsNotNull()) { mitk::DataNode *n = m_DataStorage->GetNamedNode(widgetName); if (n != nullptr) n->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); } m_RenderingManager->RequestUpdateAll(); } void QmitkStdMultiWidget::SetWidgetPlanesLocked(bool locked) { // do your job and lock or unlock slices. GetRenderWindow1()->GetSliceNavigationController()->SetSliceLocked(locked); GetRenderWindow2()->GetSliceNavigationController()->SetSliceLocked(locked); GetRenderWindow3()->GetSliceNavigationController()->SetSliceLocked(locked); } void QmitkStdMultiWidget::SetWidgetPlanesRotationLocked(bool locked) { // do your job and lock or unlock slices. GetRenderWindow1()->GetSliceNavigationController()->SetSliceRotationLocked(locked); GetRenderWindow2()->GetSliceNavigationController()->SetSliceRotationLocked(locked); GetRenderWindow3()->GetSliceNavigationController()->SetSliceRotationLocked(locked); } void QmitkStdMultiWidget::SetWidgetPlanesRotationLinked(bool link) { emit WidgetPlanesRotationLinked(link); } void QmitkStdMultiWidget::SetWidgetPlaneMode(int userMode) { MITK_DEBUG << "Changing crosshair mode to " << userMode; emit WidgetNotifyNewCrossHairMode(userMode); // Convert user interface mode to actual mode { switch (userMode) { case 0: m_MouseModeSwitcher->SetInteractionScheme(mitk::MouseModeSwitcher::InteractionScheme::MITK); break; case 1: m_MouseModeSwitcher->SetInteractionScheme(mitk::MouseModeSwitcher::InteractionScheme::ROTATION); break; case 2: m_MouseModeSwitcher->SetInteractionScheme(mitk::MouseModeSwitcher::InteractionScheme::ROTATIONLINKED); break; case 3: m_MouseModeSwitcher->SetInteractionScheme(mitk::MouseModeSwitcher::InteractionScheme::SWIVEL); break; } } } void QmitkStdMultiWidget::SetGradientBackgroundColorForRenderWindow(const mitk::Color &upper, const mitk::Color &lower, unsigned int widgetNumber) { if (widgetNumber > 3) { MITK_ERROR << "Gradientbackground for unknown widget!"; return; } m_GradientBackgroundColors[widgetNumber].first = upper; m_GradientBackgroundColors[widgetNumber].second = lower; vtkRenderer *renderer = GetRenderWindow(widgetNumber)->GetRenderer()->GetVtkRenderer(); renderer->SetBackground2(upper[0], upper[1], upper[2]); renderer->SetBackground(lower[0], lower[1], lower[2]); m_GradientBackgroundFlag = true; } void QmitkStdMultiWidget::SetGradientBackgroundColors(const mitk::Color &upper, const mitk::Color &lower) { for (unsigned int i = 0; i < 4; ++i) { vtkRenderer *renderer = GetRenderWindow(i)->GetRenderer()->GetVtkRenderer(); renderer->SetBackground2(upper[0], upper[1], upper[2]); renderer->SetBackground(lower[0], lower[1], lower[2]); } m_GradientBackgroundFlag = true; } void QmitkStdMultiWidget::SetDepartmentLogoPath(const char *path) { m_LogoRendering->SetLogoImagePath(path); mitk::BaseRenderer *renderer = mitk::BaseRenderer::GetInstance(mitkWidget4->GetRenderWindow()); m_LogoRendering->Update(renderer); RequestUpdate(); } void QmitkStdMultiWidget::SetWidgetPlaneModeToSlicing(bool activate) { if (activate) { this->SetWidgetPlaneMode(PLANE_MODE_SLICING); } } void QmitkStdMultiWidget::SetWidgetPlaneModeToRotation(bool activate) { if (activate) { this->SetWidgetPlaneMode(PLANE_MODE_ROTATION); } } void QmitkStdMultiWidget::SetWidgetPlaneModeToSwivel(bool activate) { if (activate) { this->SetWidgetPlaneMode(PLANE_MODE_SWIVEL); } } void QmitkStdMultiWidget::OnLayoutDesignChanged(int layoutDesignIndex) { switch (layoutDesignIndex) { case LAYOUT_DEFAULT: { this->changeLayoutToDefault(); break; } case LAYOUT_2D_IMAGES_UP: { this->changeLayoutTo2DImagesUp(); break; } case LAYOUT_2D_IMAGES_LEFT: { this->changeLayoutTo2DImagesLeft(); break; } case LAYOUT_BIG_3D: { this->changeLayoutToBig3D(); break; } case LAYOUT_WIDGET1: { this->changeLayoutToWidget1(); break; } case LAYOUT_WIDGET2: { this->changeLayoutToWidget2(); break; } case LAYOUT_WIDGET3: { this->changeLayoutToWidget3(); break; } case LAYOUT_2X_2D_AND_3D_WIDGET: { this->changeLayoutTo2x2Dand3DWidget(); break; } case LAYOUT_ROW_WIDGET_3_AND_4: { this->changeLayoutToRowWidget3And4(); break; } case LAYOUT_COLUMN_WIDGET_3_AND_4: { this->changeLayoutToColumnWidget3And4(); break; } case LAYOUT_ROW_WIDGET_SMALL3_AND_BIG4: { this->changeLayoutToRowWidgetSmall3andBig4(); break; } case LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4: { this->changeLayoutToSmallUpperWidget2Big3and4(); break; } case LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET: { this->changeLayoutToLeft2Dand3DRight2D(); break; } }; } void QmitkStdMultiWidget::UpdateAllWidgets() { mitkWidget1->resize(mitkWidget1Container->frameSize().width() - 1, mitkWidget1Container->frameSize().height()); mitkWidget1->resize(mitkWidget1Container->frameSize().width(), mitkWidget1Container->frameSize().height()); mitkWidget2->resize(mitkWidget2Container->frameSize().width() - 1, mitkWidget2Container->frameSize().height()); mitkWidget2->resize(mitkWidget2Container->frameSize().width(), mitkWidget2Container->frameSize().height()); mitkWidget3->resize(mitkWidget3Container->frameSize().width() - 1, mitkWidget3Container->frameSize().height()); mitkWidget3->resize(mitkWidget3Container->frameSize().width(), mitkWidget3Container->frameSize().height()); mitkWidget4->resize(mitkWidget4Container->frameSize().width() - 1, mitkWidget4Container->frameSize().height()); mitkWidget4->resize(mitkWidget4Container->frameSize().width(), mitkWidget4Container->frameSize().height()); } void QmitkStdMultiWidget::HideAllWidgetToolbars() { mitkWidget1->HideRenderWindowMenu(); mitkWidget2->HideRenderWindowMenu(); mitkWidget3->HideRenderWindowMenu(); mitkWidget4->HideRenderWindowMenu(); } void QmitkStdMultiWidget::ActivateMenuWidget(bool state) { mitkWidget1->ActivateMenuWidget(state, this); mitkWidget2->ActivateMenuWidget(state, this); mitkWidget3->ActivateMenuWidget(state, this); mitkWidget4->ActivateMenuWidget(state, this); } bool QmitkStdMultiWidget::IsMenuWidgetEnabled() const { return mitkWidget1->GetActivateMenuWidgetFlag(); } 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; } } void QmitkStdMultiWidget::ResetCrosshair() { if (m_DataStorage.IsNotNull()) { m_RenderingManager->InitializeViewsByBoundingObjects(m_DataStorage); // m_RenderingManager->InitializeViews( m_DataStorage->ComputeVisibleBoundingGeometry3D() ); // reset interactor to normal slicing this->SetWidgetPlaneMode(PLANE_MODE_SLICING); } } void QmitkStdMultiWidget::EnableColoredRectangles() { m_RectangleProps[0]->SetVisibility(1); m_RectangleProps[1]->SetVisibility(1); m_RectangleProps[2]->SetVisibility(1); m_RectangleProps[3]->SetVisibility(1); } void QmitkStdMultiWidget::DisableColoredRectangles() { m_RectangleProps[0]->SetVisibility(0); m_RectangleProps[1]->SetVisibility(0); m_RectangleProps[2]->SetVisibility(0); m_RectangleProps[3]->SetVisibility(0); } bool QmitkStdMultiWidget::IsColoredRectanglesEnabled() const { return m_RectangleProps[0]->GetVisibility() > 0; } mitk::MouseModeSwitcher *QmitkStdMultiWidget::GetMouseModeSwitcher() { return m_MouseModeSwitcher; } mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane1() { return this->m_PlaneNode1; } mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane2() { return this->m_PlaneNode2; } mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane3() { return this->m_PlaneNode3; } mitk::DataNode::Pointer QmitkStdMultiWidget::GetWidgetPlane(int id) { switch (id) { case 1: return this->m_PlaneNode1; break; case 2: return this->m_PlaneNode2; break; case 3: return this->m_PlaneNode3; break; default: return nullptr; } } diff --git a/Modules/SceneSerializationBase/src/mitkEnumerationSubclassesSerializer.cpp b/Modules/SceneSerializationBase/src/mitkEnumerationSubclassesSerializer.cpp index faa8fadd26..5e1a6e8dfd 100644 --- a/Modules/SceneSerializationBase/src/mitkEnumerationSubclassesSerializer.cpp +++ b/Modules/SceneSerializationBase/src/mitkEnumerationSubclassesSerializer.cpp @@ -1,78 +1,76 @@ /*=================================================================== 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 mitkEnumerationSubclassesSerializer_h_included #define mitkEnumerationSubclassesSerializer_h_included #include "mitkEnumerationPropertySerializer.h" #include "mitkModalityProperty.h" #include "mitkPlaneOrientationProperty.h" #include "mitkPointSetShapeProperty.h" #include "mitkRenderingModeProperty.h" -#include "mitkShaderProperty.h" #include "mitkVtkInterpolationProperty.h" #include "mitkVtkRepresentationProperty.h" #include "mitkVtkResliceInterpolationProperty.h" #include "mitkVtkScalarModeProperty.h" #include "mitkVtkVolumeRenderingProperty.h" #define MITK_REGISTER_ENUM_SUB_SERIALIZER(classname) \ \ namespace mitk \ \ { \ \ class classname##Serializer \ : public EnumerationPropertySerializer\ {public : \ \ mitkClassMacro(classname##Serializer, EnumerationPropertySerializer) itkFactorylessNewMacro(Self) \ itkCloneMacro(Self) \ \ virtual BaseProperty::Pointer Deserialize(TiXmlElement * element) override{if (!element) return nullptr; \ const char *sa(element->Attribute("value")); \ \ std::string s(sa ? sa : ""); \ classname::Pointer property = classname::New(); \ property->SetValue(s); \ \ return property.GetPointer(); \ } \ \ protected: \ classname##Serializer() {} \ virtual ~classname##Serializer() {} \ \ } \ ; \ \ } \ \ MITK_REGISTER_SERIALIZER(classname##Serializer); MITK_REGISTER_ENUM_SUB_SERIALIZER(PlaneOrientationProperty); -MITK_REGISTER_ENUM_SUB_SERIALIZER(ShaderProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(VtkInterpolationProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(VtkRepresentationProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(VtkResliceInterpolationProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(VtkScalarModeProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(VtkVolumeRenderingProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(ModalityProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(RenderingModeProperty); MITK_REGISTER_ENUM_SUB_SERIALIZER(PointSetShapeProperty); #endif diff --git a/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp b/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp index aff5341864..710694c5c3 100644 --- a/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp +++ b/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp @@ -1,281 +1,279 @@ /*=================================================================== 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 "mitkTestingMacros.h" #include "mitkCoreObjectFactory.h" #include "mitkBaseProperty.h" #include "mitkProperties.h" #include #include #include #include /* #include #include #include */ #include //#include //#include #include #include #include #include -#include #include #include #include #include #include #include #include #include "mitkBasePropertySerializer.h" #include "mitkPropertyList.h" #include "mitkPropertyListSerializer.h" #include #include #include #include /* #include #include #include #include #include #include #include #include #include #include */ void TestAllProperties(const mitk::PropertyList *propList); /**Documentation * \brief Test for all PropertySerializer classes. * */ int mitkPropertySerializationTest(int /* argc */, char * /*argv*/ []) { MITK_TEST_BEGIN("PropertySerializationTest"); mitk::PropertyListSerializer::Pointer serializer = mitk::PropertyListSerializer::New(); // make sure something from the lib is actually used (registration of // serializers) /* build list of properties that will be serialized and deserialized */ mitk::PropertyList::Pointer propList = mitk::PropertyList::New(); propList->SetProperty("booltrue", mitk::BoolProperty::New(true)); propList->SetProperty("boolfalse", mitk::BoolProperty::New(false)); propList->SetProperty("int", mitk::IntProperty::New(-32)); propList->SetProperty("float", mitk::FloatProperty::New(-31.337)); propList->SetProperty("double", mitk::DoubleProperty::New(-31.337)); propList->SetProperty("string", mitk::StringProperty::New("Hello MITK")); mitk::Point3D p3d; mitk::FillVector3D(p3d, 1.0, 2.2, -3.3); propList->SetProperty("p3d", mitk::Point3dProperty::New(p3d)); mitk::Point3I p3i; mitk::FillVector3D(p3i, 1, 2, -3); propList->SetProperty("p3i", mitk::Point3iProperty::New(p3i)); mitk::Point4D p4d; mitk::FillVector4D(p4d, 1.5, 2.6, -3.7, 4.44); propList->SetProperty("p4d", mitk::Point4dProperty::New(p4d)); mitk::Vector3D v3d; mitk::FillVector3D(v3d, 1.0, 2.2, -3.3); propList->SetProperty("v3d", mitk::Vector3DProperty::New(v3d)); propList->SetProperty("annotation", mitk::AnnotationProperty::New("My Annotation", p3d)); propList->SetProperty("clipping", mitk::ClippingProperty::New(p3d, v3d)); propList->SetProperty("color", mitk::ColorProperty::New(1.0, 0.2, 0.2)); // mitk::EnumerationProperty::Pointer en = mitk::EnumerationProperty::New(); // en->AddEnum("PC", 1); en->AddEnum("Playstation", 2); en->AddEnum("Wii", 111); en->AddEnum("XBox", 7); // en->SetValue("XBox"); // propList->SetProperty("enum", en); /* propList->SetProperty("gridrep", mitk::GridRepresentationProperty::New(2)); propList->SetProperty("gridvol", mitk::GridVolumeMapperProperty::New(0)); propList->SetProperty("OrganTypeProperty", mitk::OrganTypeProperty::New("Larynx")); */ propList->SetProperty("modality", mitk::ModalityProperty::New("Color Doppler")); // propList->SetProperty("OdfNormalizationMethodProperty", mitk::OdfNormalizationMethodProperty::New("Global // Maximum")); // propList->SetProperty("OdfScaleByProperty", mitk::OdfScaleByProperty::New("Principal Curvature")); propList->SetProperty("PlaneOrientationProperty", mitk::PlaneOrientationProperty::New("Arrows in positive direction")); - propList->SetProperty("ShaderProperty", mitk::ShaderProperty::New("fixed")); propList->SetProperty("VtkInterpolationProperty", mitk::VtkInterpolationProperty::New("Gouraud")); propList->SetProperty("VtkRepresentationProperty", mitk::VtkRepresentationProperty::New("Surface")); propList->SetProperty("VtkResliceInterpolationProperty", mitk::VtkResliceInterpolationProperty::New("Cubic")); propList->SetProperty("VtkScalarModeProperty", mitk::VtkScalarModeProperty::New("PointFieldData")); propList->SetProperty("VtkVolumeRenderingProperty", mitk::VtkVolumeRenderingProperty::New("COMPOSITE")); mitk::BoolLookupTable blt; blt.SetTableValue(0, true); blt.SetTableValue(1, false); blt.SetTableValue(2, true); propList->SetProperty("BoolLookupTableProperty", mitk::BoolLookupTableProperty::New(blt)); mitk::FloatLookupTable flt; flt.SetTableValue(0, 3.1); flt.SetTableValue(1, 3.3); flt.SetTableValue(2, 7.0); propList->SetProperty("FloatLookupTableProperty", mitk::FloatLookupTableProperty::New(flt)); mitk::IntLookupTable ilt; ilt.SetTableValue(0, 3); ilt.SetTableValue(1, 2); ilt.SetTableValue(2, 11); propList->SetProperty("IntLookupTableProperty", mitk::IntLookupTableProperty::New(ilt)); mitk::StringLookupTable slt; slt.SetTableValue(0, "Hello"); slt.SetTableValue(1, "MITK"); slt.SetTableValue(2, "world"); propList->SetProperty("StringLookupTableProperty", mitk::StringLookupTableProperty::New(slt)); propList->SetProperty("GroupTagProperty", mitk::GroupTagProperty::New()); propList->SetProperty("LevelWindowProperty", mitk::LevelWindowProperty::New(mitk::LevelWindow(100.0, 50.0))); mitk::LookupTable::Pointer lt = mitk::LookupTable::New(); lt->ChangeOpacityForAll(0.25); lt->ChangeOpacity(17, 0.88); propList->SetProperty("LookupTableProperty", mitk::LookupTableProperty::New(lt)); propList->SetProperty("StringProperty", mitk::StringProperty::New("Oh why, gruel world")); // mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); // tf->SetTransferFunctionMode(1); // propList->SetProperty("TransferFunctionProperty", mitk::TransferFunctionProperty::New(tf)); MITK_TEST_CONDITION_REQUIRED(propList->GetMap()->size() > 0, "Initialize PropertyList"); TestAllProperties(propList); /* test default property lists of basedata objects */ // activate the following tests after MaterialProperty is deleted mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(mitk::PointSet::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::Image::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::Surface::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::VtkWidgetRendering::New()); TestAllProperties(node->GetPropertyList()); /* node->SetData(mitk::Contour::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::ContourSet::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::Mesh::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::Cone::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::Cuboid::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::Cylinder::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::Ellipsoid::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::ExtrudedContour::New()); TestAllProperties(node->GetPropertyList()); node->SetData(mitk::Plane::New()); TestAllProperties(node->GetPropertyList()); //node->SetData(mitk::TrackingVolume::New()); // TrackingVolume is in IGT Module, it does not have special properties, therefore we skip it here //TestAllProperties(node->GetPropertyList()); node->SetData(mitk::UnstructuredGrid::New()); TestAllProperties(node->GetPropertyList()); */ /* untested base data types: BaseDataTestImplementation RenderWindowFrame GeometryData mitk::PlaneGeometryData GradientBackground ItkBaseDataAdapter SlicedData QBallImage SeedsImage TensorImage BoundingObject BoundingObjectGroup */ MITK_TEST_END(); } void TestAllProperties(const mitk::PropertyList *propList) { assert(propList); /* try to serialize each property in the list, then deserialize again and check for equality */ for (mitk::PropertyList::PropertyMap::const_iterator it = propList->GetMap()->begin(); it != propList->GetMap()->end(); ++it) { const mitk::BaseProperty *prop = it->second; // construct name of serializer class std::string serializername = std::string(prop->GetNameOfClass()) + "Serializer"; std::list allSerializers = itk::ObjectFactoryBase::CreateAllInstance(serializername.c_str()); MITK_TEST_CONDITION(allSerializers.size() > 0, std::string("Creating serializers for ") + serializername); if (allSerializers.size() == 0) { MITK_TEST_OUTPUT(<< "serialization not possible, skipping " << prop->GetNameOfClass()); continue; } if (allSerializers.size() > 1) { MITK_TEST_OUTPUT(<< "Warning: " << allSerializers.size() << " serializers found for " << prop->GetNameOfClass() << "testing only the first one."); } mitk::BasePropertySerializer *serializer = dynamic_cast(allSerializers.begin()->GetPointer()); MITK_TEST_CONDITION(serializer != nullptr, serializername + std::string(" is valid")); if (serializer != nullptr) { serializer->SetProperty(prop); TiXmlElement *valueelement = nullptr; try { valueelement = serializer->Serialize(); } catch (...) { } MITK_TEST_CONDITION(valueelement != nullptr, std::string("Serialize property with ") + serializername); if (valueelement == nullptr) { MITK_TEST_OUTPUT(<< "serialization failed, skipping deserialization"); continue; } mitk::BaseProperty::Pointer deserializedProp = serializer->Deserialize(valueelement); MITK_TEST_CONDITION(deserializedProp.IsNotNull(), "serializer created valid property"); if (deserializedProp.IsNotNull()) { MITK_TEST_CONDITION(*(deserializedProp.GetPointer()) == *prop, "deserialized property equals initial property for type " << prop->GetNameOfClass()); } } else { MITK_TEST_OUTPUT(<< "created serializer object is of class " << allSerializers.begin()->GetPointer()->GetNameOfClass()) } } // for all properties } diff --git a/Modules/VtkShaders/CMakeLists.txt b/Modules/VtkShaders/CMakeLists.txt deleted file mode 100644 index 88ec853c71..0000000000 --- a/Modules/VtkShaders/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -MITK_CREATE_MODULE(VtkShaders - DEPENDS MitkCore - AUTOLOAD_WITH MitkCore -) diff --git a/Modules/VtkShaders/files.cmake b/Modules/VtkShaders/files.cmake deleted file mode 100644 index 1e8df320a0..0000000000 --- a/Modules/VtkShaders/files.cmake +++ /dev/null @@ -1,13 +0,0 @@ -set(CPP_FILES - vtkXMLMaterial.cpp - vtkXMLMaterialParser.cpp - vtkXMLShader.cpp - mitkVtkShaderRepository.cpp - mitkVtkShadersActivator.cpp - mitkVtkShaderProgram.cpp -) - - -set(RESOURCE_FILES - Shaders/mitkShaderLighting.xml -) diff --git a/Modules/VtkShaders/resource/Shaders/mitkShaderLighting.xml b/Modules/VtkShaders/resource/Shaders/mitkShaderLighting.xml deleted file mode 100644 index 5f4e2c54c7..0000000000 --- a/Modules/VtkShaders/resource/Shaders/mitkShaderLighting.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - attribute vec3 scalars; - - uniform vec3 LightPosition; - uniform vec3 SkyColor; - uniform vec3 GroundColor; - - varying vec3 DiffuseColor; - - - void main(void) - { - vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Vertex); - vec3 tnorm = normalize(gl_NormalMatrix * gl_Normal); - vec3 lightVec = normalize(LightPosition - ecPosition); - float costheta = dot(tnorm, lightVec); - float a = 0.5 + 0.5 * costheta; - - DiffuseColor = mix(GroundColor, SkyColor, a); - - gl_Position = ftransform(); - - } - - - varying vec3 DiffuseColor; - void main(void) - { - gl_FragColor = vec4(DiffuseColor, 1.0); - } - - diff --git a/Modules/VtkShaders/src/mitkVtkShaderProgram.h b/Modules/VtkShaders/src/mitkVtkShaderProgram.h deleted file mode 100644 index 816c04a619..0000000000 --- a/Modules/VtkShaders/src/mitkVtkShaderProgram.h +++ /dev/null @@ -1,58 +0,0 @@ -/*=================================================================== - -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 _MITKVTKSHADERPROGRAM_H_ -#define _MITKVTKSHADERPROGRAM_H_ - -#include - -#include -#include - -namespace mitk -{ - /** - * \brief SHADERTODO - */ - class VtkShaderProgram : public IShaderRepository::ShaderProgram - { - public: - mitkClassMacro(VtkShaderProgram, IShaderRepository::ShaderProgram) itkFactorylessNewMacro(Self) - - /** - * Constructor - */ - VtkShaderProgram(); - - /** - * Destructor - */ - virtual ~VtkShaderProgram(); - - virtual void Activate() override; - virtual void Deactivate() override; - - void SetVtkShaderProgram(vtkSmartPointer p); - vtkSmartPointer GetVtkShaderProgram() const; - itk::TimeStamp &GetShaderTimestampUpdate(); - - private: - vtkSmartPointer m_VtkShaderProgram; - itk::TimeStamp m_ShaderTimestampUpdate; - }; - -} // end of namespace mitk -#endif diff --git a/Modules/VtkShaders/src/mitkVtkShaderRepository.h b/Modules/VtkShaders/src/mitkVtkShaderRepository.h deleted file mode 100644 index 01f67664e7..0000000000 --- a/Modules/VtkShaders/src/mitkVtkShaderRepository.h +++ /dev/null @@ -1,164 +0,0 @@ -/*=================================================================== - -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 _MITKVTKSHADERREPOSITORY_H_ -#define _MITKVTKSHADERREPOSITORY_H_ - -#include "mitkIShaderRepository.h" -#include -#include - -class vtkXMLDataElement; -class vtkXMLMaterial; -class vtkProperty; - -namespace mitk -{ - /** - * \brief Management class for vtkShader XML descriptions. - * - * Looks for all XML shader files in a given directory and adds default properties - * for each shader object (shader uniforms) to the specified mitk::DataNode. - * - * Additionally, it provides a utility function for applying properties for shaders - * in mappers. - */ - class VtkShaderRepository : public IShaderRepository - { - protected: - class Shader : public IShaderRepository::Shader - { - public: - mitkClassMacro(Shader, IShaderRepository::Shader) itkFactorylessNewMacro(Self) - - class Uniform : public itk::Object - { - public: - mitkClassMacroItkParent(Uniform, itk::Object) itkFactorylessNewMacro(Self) - - enum Type { - glsl_none, - glsl_float, - glsl_vec2, - glsl_vec3, - glsl_vec4, - glsl_int, - glsl_ivec2, - glsl_ivec3, - glsl_ivec4 - }; - - /** - * Constructor - */ - Uniform(); - - /** - * Destructor - */ - ~Uniform(); - - Type type; - std::string name; - - int defaultInt[4]; - float defaultFloat[4]; - - void LoadFromXML(vtkXMLDataElement *e); - }; - - std::list uniforms; - - /** - * Constructor - */ - Shader(); - - /** - * Destructor - */ - ~Shader(); - - void SetVertexShaderCode(const std::string &code); - std::string GetVertexShaderCode() const; - - void SetFragmentShaderCode(const std::string &code); - std::string GetFragmentShaderCode() const; - - void SetGeometryShaderCode(const std::string &code); - std::string GetGeometryShaderCode() const; - - std::list GetUniforms() const; - - private: - friend class VtkShaderRepository; - - std::string m_VertexShaderCode; - std::string m_FragmentShaderCode; - std::string m_GeometryShaderCode; - - void LoadXmlShader(std::istream &stream); - }; - - void LoadShaders(); - - Shader::Pointer GetShaderImpl(const std::string &name) const; - - private: - std::list shaders; - - static int shaderId; - static const bool debug; - - public: - /** - * Constructor - */ - VtkShaderRepository(); - - /** - * Destructor - */ - ~VtkShaderRepository(); - - ShaderProgram::Pointer CreateShaderProgram() override; - - std::list GetShaders() const override; - - IShaderRepository::Shader::Pointer GetShader(const std::string &name) const override; - - IShaderRepository::Shader::Pointer GetShader(int id) const override; - - /** \brief Adds all parsed shader uniforms to property list of the given DataNode; - * used by mappers. - */ - void AddDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) const override; - - /** \brief Applies shader and shader specific variables of the specified DataNode - * to the VTK object by updating the shader variables of its vtkProperty. - */ - - int LoadShader(std::istream &stream, const std::string &name) override; - - bool UnloadShader(int id) override; - - void UpdateShaderProgram(mitk::IShaderRepository::ShaderProgram *shaderProgram, - DataNode *node, - BaseRenderer *renderer) const override; - }; - -} // end of namespace mitk -#endif diff --git a/Modules/VtkShaders/src/vtkXMLMaterial.cpp b/Modules/VtkShaders/src/vtkXMLMaterial.cpp deleted file mode 100644 index ab5602a23d..0000000000 --- a/Modules/VtkShaders/src/vtkXMLMaterial.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - -/*========================================================================= - - Program: Visualization Toolkit - Module: vtkXMLMaterial.cxx - - Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen - All rights reserved. - See Copyright.txt or http://www.kitware.com/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notice for more information. - -=========================================================================*/ - -#include "vtkXMLMaterial.h" - -#include "vtkObjectFactory.h" -#include "vtkSmartPointer.h" -#include "vtkXMLDataElement.h" -#include "vtkXMLMaterialParser.h" -#include "vtkXMLShader.h" - -#include -#include - -class vtkXMLMaterialInternals -{ -public: - typedef std::vector VectorOfElements; - typedef std::vector> VectorOfShaders; - VectorOfElements Properties; - VectorOfShaders VertexShaders; - VectorOfShaders FragmentShaders; - VectorOfShaders GeometryShaders; - VectorOfElements Textures; - void Initialize() - { - this->Properties.clear(); - this->VertexShaders.clear(); - this->FragmentShaders.clear(); - this->GeometryShaders.clear(); - this->Textures.clear(); - } -}; - -vtkStandardNewMacro(vtkXMLMaterial); - -//----------------------------------------------------------------------------- -vtkXMLMaterial::vtkXMLMaterial() -{ - this->RootElement = nullptr; - this->Internals = new vtkXMLMaterialInternals; -} - -//----------------------------------------------------------------------------- -vtkXMLMaterial::~vtkXMLMaterial() -{ - this->SetRootElement(nullptr); - delete this->Internals; -} - -vtkXMLMaterial *vtkXMLMaterial::CreateInstance(const char *name) -{ - if (!name) - { - return nullptr; - } - - vtkXMLMaterialParser *parser = vtkXMLMaterialParser::New(); - vtkXMLMaterial *material = vtkXMLMaterial::New(); - parser->SetMaterial(material); - - // First, look for material library files. - // Then, look for Repository files. - - char *filename = vtkXMLShader::LocateFile(name); - if (filename) - { - parser->SetFileName(filename); - delete[] filename; - parser->Parse(); - parser->Delete(); - return material; - } - - parser->Delete(); - material->Delete(); - return nullptr; -} - -//----------------------------------------------------------------------------- -void vtkXMLMaterial::SetRootElement(vtkXMLDataElement *root) -{ - this->Internals->Initialize(); - - vtkSetObjectBodyMacro(RootElement, vtkXMLDataElement, root); - if (this->RootElement) - { - // Update the internal data structure to - // avoid repeated searches. - int numElems = this->RootElement->GetNumberOfNestedElements(); - for (int i = 0; i < numElems; i++) - { - vtkXMLDataElement *elem = this->RootElement->GetNestedElement(i); - const char *name = elem->GetName(); - if (!name) - { - continue; - } - if (strcmp(name, "Property") == 0) - { - this->Internals->Properties.push_back(elem); - } - else if (strcmp(name, "Shader") == 0) - { - vtkXMLShader *shader = vtkXMLShader::New(); - shader->SetRootElement(elem); - - switch (shader->GetScope()) - { - case vtkXMLShader::SCOPE_VERTEX: - this->Internals->VertexShaders.push_back(shader); - break; - case vtkXMLShader::SCOPE_FRAGMENT: - this->Internals->FragmentShaders.push_back(shader); - break; - case vtkXMLShader::SCOPE_GEOMETRY: - this->Internals->GeometryShaders.push_back(shader); - break; - default: - vtkErrorMacro("Invalid scope for shader: " << shader->GetName()); - } - - shader->Delete(); - } - else if (strcmp(name, "Texture") == 0) - { - this->Internals->Textures.push_back(elem); - } - } - } -} - -//----------------------------------------------------------------------------- -int vtkXMLMaterial::GetNumberOfProperties() -{ - return static_cast(this->Internals->Properties.size()); -} - -//----------------------------------------------------------------------------- -int vtkXMLMaterial::GetNumberOfTextures() -{ - return static_cast(this->Internals->Textures.size()); -} - -//----------------------------------------------------------------------------- -int vtkXMLMaterial::GetNumberOfVertexShaders() -{ - return static_cast(this->Internals->VertexShaders.size()); -} - -//----------------------------------------------------------------------------- -int vtkXMLMaterial::GetNumberOfFragmentShaders() -{ - return static_cast(this->Internals->FragmentShaders.size()); -} - -int vtkXMLMaterial::GetNumberOfGeometryShaders() -{ - return static_cast(this->Internals->GeometryShaders.size()); -} - -//----------------------------------------------------------------------------- -vtkXMLDataElement *vtkXMLMaterial::GetProperty(int id) -{ - if (id < this->GetNumberOfProperties()) - { - return this->Internals->Properties[id]; - } - return nullptr; -} - -//----------------------------------------------------------------------------- -vtkXMLDataElement *vtkXMLMaterial::GetTexture(int index) -{ - if (index < this->GetNumberOfTextures()) - { - return this->Internals->Textures[index]; - } - return nullptr; -} - -//----------------------------------------------------------------------------- -vtkXMLShader *vtkXMLMaterial::GetVertexShader(int id) -{ - if (id < this->GetNumberOfVertexShaders()) - { - return this->Internals->VertexShaders[id].GetPointer(); - } - return nullptr; -} - -//----------------------------------------------------------------------------- -vtkXMLShader *vtkXMLMaterial::GetFragmentShader(int id) -{ - if (id < this->GetNumberOfFragmentShaders()) - { - return this->Internals->FragmentShaders[id].GetPointer(); - } - return nullptr; -} - -vtkXMLShader *vtkXMLMaterial::GetGeometryShader(int id) -{ - if (id < this->GetNumberOfGeometryShaders()) - { - return this->Internals->GeometryShaders[id].GetPointer(); - } - return nullptr; -} - -//---------------------------------------------------------------------------- - -// ---------------------------------------------------------------------------- -// Description: -// Get the style the shaders. -// \post valid_result: result==1 || result==2 -int vtkXMLMaterial::GetShaderStyle() -{ - int result = 1; - int vStyle = 0; - if (this->GetVertexShader()) - { - vStyle = this->GetVertexShader()->GetStyle(); - } - int fStyle = 0; - if (this->GetFragmentShader()) - { - fStyle = this->GetFragmentShader()->GetStyle(); - } - int gStyle = 0; - if (this->GetGeometryShader()) - { - gStyle = this->GetGeometryShader()->GetStyle(); - } - if (vStyle != 0 && fStyle != 0 && !gStyle && vStyle != fStyle) - { - vtkErrorMacro(<< "vertex shader and fragment shader style differ."); - } - else - { - if (vStyle != 0) - { - result = vStyle; - } - else - { - result = fStyle; - } - } - - assert("post: valid_result" && (result == 1 || result == 2)); - return result; -} - -//----------------------------------------------------------------------------- -void vtkXMLMaterial::PrintSelf(ostream &os, vtkIndent indent) -{ - this->Superclass::PrintSelf(os, indent); - os << indent << "Number of Properties: " << this->GetNumberOfProperties() << endl; - os << indent << "Number of Vertex Shaders: " << this->GetNumberOfVertexShaders() << endl; - os << indent << "Number of Fragment Shaders: " << this->GetNumberOfFragmentShaders() << endl; - os << indent << "RootElement: "; - if (this->RootElement) - { - os << endl; - this->RootElement->PrintSelf(os, indent.GetNextIndent()); - } - else - { - os << "(null)" << endl; - } -} diff --git a/Modules/VtkShaders/src/vtkXMLMaterial.h b/Modules/VtkShaders/src/vtkXMLMaterial.h deleted file mode 100644 index 61c675f58e..0000000000 --- a/Modules/VtkShaders/src/vtkXMLMaterial.h +++ /dev/null @@ -1,122 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - -/*========================================================================= - - Program: Visualization Toolkit - Module: vtkXMLMaterial.h - - Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen - All rights reserved. - See Copyright.txt or http://www.kitware.com/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notice for more information. - -=========================================================================*/ -// .NAME vtkXMLMaterial - encapsulates a VTK Material description. -// .SECTION Description -// vtkXMLMaterial encapsulates VTK Material description. It keeps a pointer -// to vtkXMLDataElement that defines the material and provides -// access to Shaders/Properties defined in it. -// .SECTION Thanks -// Shader support in VTK includes key contributions by Gary Templet at -// Sandia National Labs. - -#ifndef __vtkXMLMaterial_h -#define __vtkXMLMaterial_h - -#include "vtkObject.h" -#include "vtkRenderingCoreModule.h" // For export macro - -class vtkXMLDataElement; -class vtkXMLMaterialInternals; -class vtkXMLShader; - -class vtkXMLMaterial : public vtkObject -{ -public: - static vtkXMLMaterial *New(); - vtkTypeMacro(vtkXMLMaterial, vtkObject); - void PrintSelf(ostream &os, vtkIndent indent) override; - - // Description: - // Create a new instance. It searches for the material - // using the following order: first, check the MaterialLibrary; second, - // treat the name as an absolute path and try to locate it; third, - // search the Material repository. Returns null is it fails to - // locate the material. - static vtkXMLMaterial *CreateInstance(const char *name); - - // Description: - // Get number of elements of type Property. - int GetNumberOfProperties(); - - // Description: - // Get number of elements of type Texture. - int GetNumberOfTextures(); - - // Description: - // Get number of Vertex shaders. - int GetNumberOfVertexShaders(); - - // Description: - // Get number of fragment shaders. - int GetNumberOfFragmentShaders(); - int GetNumberOfGeometryShaders(); - - // Description: - // Get the ith vtkXMLDataElement of type . - vtkXMLDataElement *GetProperty(int id = 0); - - // Description: - // Get the ith vtkXMLDataElement of type . - vtkXMLDataElement *GetTexture(int id = 0); - - // Description: - // Get the ith vtkXMLDataElement of type . - vtkXMLShader *GetVertexShader(int id = 0); - - // Description: - // Get the ith vtkXMLDataElement of type . - vtkXMLShader *GetFragmentShader(int id = 0); - - vtkXMLShader *GetGeometryShader(int id = 0); - - // Description: - // Get/Set the XML root element that describes this material. - vtkGetObjectMacro(RootElement, vtkXMLDataElement); - void SetRootElement(vtkXMLDataElement *); - - // Description: - // Get the style the shaders. - // \post valid_result: result==1 || result==2 - int GetShaderStyle(); - -protected: - vtkXMLMaterial(); - ~vtkXMLMaterial(); - - vtkXMLDataElement *RootElement; - vtkXMLMaterialInternals *Internals; - -private: - vtkXMLMaterial(const vtkXMLMaterial &); // Not implemented. - void operator=(const vtkXMLMaterial &); // Not implemented. -}; - -#endif diff --git a/Modules/VtkShaders/src/vtkXMLMaterialParser.cpp b/Modules/VtkShaders/src/vtkXMLMaterialParser.cpp deleted file mode 100644 index 0a85a9a7f6..0000000000 --- a/Modules/VtkShaders/src/vtkXMLMaterialParser.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - -/*========================================================================= - - Program: Visualization Toolkit - Module: vtkXMLMaterialParser.cxx - - Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen - All rights reserved. - See Copyright.txt or http://www.kitware.com/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notice for more information. - -=========================================================================*/ - -/* - * Copyright 2003 Sandia Corporation. - * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive - * license for use of this work by or on behalf of the - * U.S. Government. Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that this Notice and any - * statement of authorship are reproduced on all copies. - */ - -#include "vtkXMLMaterialParser.h" - -#include "vtkObjectFactory.h" -#include "vtkSmartPointer.h" -#include "vtkXMLDataElement.h" -#include "vtkXMLMaterial.h" - -#include "vtkXMLUtilities.h" - -#include - -//----------------------------------------------------------------------------- -class vtkXMLMaterialParserInternals -{ -public: - typedef std::vector> VectorOfElements; - VectorOfElements Stack; -}; - -//----------------------------------------------------------------------------- -vtkStandardNewMacro(vtkXMLMaterialParser); -vtkCxxSetObjectMacro(vtkXMLMaterialParser, Material, vtkXMLMaterial); - -//----------------------------------------------------------------------------- -vtkXMLMaterialParser::vtkXMLMaterialParser() -{ - this->Material = vtkXMLMaterial::New(); - this->Material->Register(this); - this->Material->Delete(); - this->Internals = new vtkXMLMaterialParserInternals; -} - -//----------------------------------------------------------------------------- -vtkXMLMaterialParser::~vtkXMLMaterialParser() -{ - delete this->Internals; - this->SetMaterial(nullptr); -} - -//----------------------------------------------------------------------------- -int vtkXMLMaterialParser::Parse(const char *str) -{ - return this->Superclass::Parse(str); -} - -//----------------------------------------------------------------------------- -int vtkXMLMaterialParser::Parse(const char *str, unsigned int length) -{ - return this->Superclass::Parse(str, length); -} - -//----------------------------------------------------------------------------- -int vtkXMLMaterialParser::Parse() -{ - this->Internals->Stack.clear(); - return this->Superclass::Parse(); -} - -//----------------------------------------------------------------------------- -int vtkXMLMaterialParser::InitializeParser() -{ - int ret = this->Superclass::InitializeParser(); - if (ret) - { - this->Internals->Stack.clear(); - } - return ret; -} - -//----------------------------------------------------------------------------- -void vtkXMLMaterialParser::StartElement(const char *name, const char **atts) -{ - vtkXMLDataElement *element = vtkXMLDataElement::New(); - element->SetName(name); - element->SetXMLByteIndex(this->GetXMLByteIndex()); - vtkXMLUtilities::ReadElementFromAttributeArray(element, atts, VTK_ENCODING_NONE); - const char *id = element->GetAttribute("id"); - if (id) - { - element->SetId(id); - } - this->Internals->Stack.push_back(element); - element->Delete(); -} - -//----------------------------------------------------------------------------- -void vtkXMLMaterialParser::EndElement(const char *vtkNotUsed(name)) -{ - vtkXMLDataElement *finished = this->Internals->Stack.back().GetPointer(); - int prev_pos = static_cast(this->Internals->Stack.size()) - 2; - if (prev_pos >= 0) - { - this->Internals->Stack[prev_pos].GetPointer()->AddNestedElement(finished); - } - else - { - this->Material->SetRootElement(finished); - } - - this->Internals->Stack.pop_back(); -} - -//----------------------------------------------------------------------------- -void vtkXMLMaterialParser::CharacterDataHandler(const char *inData, int inLength) -{ - if (this->Internals->Stack.size() > 0) - { - vtkXMLDataElement *elem = this->Internals->Stack.back().GetPointer(); - elem->AddCharacterData(inData, inLength); - } - /* - // this wont happen as the XML parser will flag it as an error. - else - { - vtkErrorMacro("Character data not enclosed in XML tags"); - } - */ -} - -//----------------------------------------------------------------------------- -void vtkXMLMaterialParser::PrintSelf(ostream &os, vtkIndent indent) -{ - this->Superclass::PrintSelf(os, indent); - os << indent << "Material: "; - this->Material->PrintSelf(os, indent.GetNextIndent()); -} diff --git a/Modules/VtkShaders/src/vtkXMLMaterialParser.h b/Modules/VtkShaders/src/vtkXMLMaterialParser.h deleted file mode 100644 index 893c94c976..0000000000 --- a/Modules/VtkShaders/src/vtkXMLMaterialParser.h +++ /dev/null @@ -1,140 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - -/*========================================================================= - - Program: Visualization Toolkit - Module: vtkXMLMaterialParser.h - - Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen - All rights reserved. - See Copyright.txt or http://www.kitware.com/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notice for more information. - -=========================================================================*/ - -/* - * Copyright 2004 Sandia Corporation. - * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive - * license for use of this work by or on behalf of the - * U.S. Government. Redistribution and use in source and binary forms, with - * or without modification, are permitted provided that this Notice and any - * statement of authorship are reproduced on all copies. - */ - -// .NAME vtkXMLMaterialParser - Parses VTK Material file -// -// .SECTION Description -// vtkXMLMaterialParser parses a VTK Material file and provides that file's -// description of a number of vertex and fragment shaders along with data -// values specified for data members of vtkProperty. This material is to be -// applied to an actor through it's vtkProperty and augments VTK's concept -// of a vtkProperty to include explicitly include vertex and fragment shaders -// and parameter settings for those shaders. This effectively makes reflectance -// models and other shaders a material property. If no shaders are specified -// VTK should default to standard rendering. -// -// .SECTION Design -// vtkXMLMaterialParser provides access to 3 distinct types of first-level -// vtkXMLDataElements that describe a VTK material. These elements are as -// follows: -// -// vtkProperty - describe values for vtkProperty data members -// -// vtkVertexShader - a vertex shader and enough information to -// install it into the hardware rendering pipeline including values for -// specific shader parameters and structures. -// -// vtkFragmentShader - a fragment shader and enough information to -// install it into the hardware rendering pipeline including values for -// specific shader parameters and structures. -// -// The design of the material file closely follows that of vtk's xml -// descriptions of it's data sets. This allows use of the very handy -// vtkXMLDataElement which provides easy access to an xml element's -// attribute values. Inlined data is currently not handled. -// -// Ideally this class would be a Facade to a DOM parser, but VTK only -// provides access to expat, a SAX parser. Other vtk classes that parse -// xml files are tuned to read vtkDataSets and don't provide the functionality -// to handle generic xml data. As such they are of little use here. -// -// This class may be extended for better data handling or may become a -// Facade to a DOM parser should on become part of the VTK code base. -// .SECTION Thanks -// Shader support in VTK includes key contributions by Gary Templet at -// Sandia National Labs. - -#ifndef __vtkXMLMaterialParser_h -#define __vtkXMLMaterialParser_h - -#include "vtkRenderingCoreModule.h" // For export macro -#include "vtkXMLParser.h" - -class vtkXMLMaterial; -class vtkXMLMaterialParserInternals; - -class vtkXMLMaterialParser : public vtkXMLParser -{ -public: - static vtkXMLMaterialParser *New(); - vtkTypeMacro(vtkXMLMaterialParser, vtkXMLParser); - void PrintSelf(ostream &os, vtkIndent indent) override; - - // Description: - // Set/Get the vtkXMLMaterial representation of the parsed material. - vtkGetObjectMacro(Material, vtkXMLMaterial); - void SetMaterial(vtkXMLMaterial *); - - // Description: - // Overridden to initialize the internal structures before - // the parsing begins. - virtual int Parse() override; - virtual int Parse(const char *inputString) override; - virtual int Parse(const char *inputString, unsigned int length) override; - - // Description: - // Overridden to clean up internal structures before the chunk-parsing - // begins. - virtual int InitializeParser() override; - -protected: - vtkXMLMaterialParser(); - ~vtkXMLMaterialParser(); - - // Description: - // Event for handling the start of an element - virtual void StartElement(const char *name, const char **atts) override; - - // Description: - // Event for handling the end of an element - virtual void EndElement(const char *) override; - - // Description: - // Handle character data, not yet implemented - virtual void CharacterDataHandler(const char *data, int length) override; - - vtkXMLMaterial *Material; - vtkXMLMaterialParserInternals *Internals; - -private: - vtkXMLMaterialParser(const vtkXMLMaterialParser &); // Not implemented - void operator=(const vtkXMLMaterialParser &); // Not implemented -}; -#endif diff --git a/Modules/VtkShaders/src/vtkXMLShader.cpp b/Modules/VtkShaders/src/vtkXMLShader.cpp deleted file mode 100644 index 0955aa6da8..0000000000 --- a/Modules/VtkShaders/src/vtkXMLShader.cpp +++ /dev/null @@ -1,293 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - -/*========================================================================= - - Program: Visualization Toolkit - Module: vtkXMLShader.cxx - - Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen - All rights reserved. - See Copyright.txt or http://www.kitware.com/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notice for more information. - -=========================================================================*/ -#include "vtkXMLShader.h" - -#include "vtkObjectFactory.h" -#include "vtkXMLDataElement.h" - -#include -#include - -vtkStandardNewMacro(vtkXMLShader); -vtkCxxSetObjectMacro(vtkXMLShader, SourceLibraryElement, vtkXMLDataElement); -//----------------------------------------------------------------------------- -vtkXMLShader::vtkXMLShader() : Code(nullptr), RootElement(nullptr), SourceLibraryElement(nullptr), Args(nullptr) -{ -} - -//----------------------------------------------------------------------------- -vtkXMLShader::~vtkXMLShader() -{ - if (this->RootElement) - { - this->RootElement->UnRegister(this); - this->RootElement = nullptr; - } - this->SetSourceLibraryElement(nullptr); - this->SetCode(nullptr); - this->CleanupArgs(); -} - -//----------------------------------------------------------------------------- -void vtkXMLShader::SetRootElement(vtkXMLDataElement *root) -{ - vtkSetObjectBodyMacro(RootElement, vtkXMLDataElement, root); - this->SetCode(nullptr); - this->SetSourceLibraryElement(nullptr); // release the SourceLibrary element. -} - -//----------------------------------------------------------------------------- -// Note that this method allocates a new string which must be deleted by -// the caller. -char *vtkXMLShader::LocateFile(const char *filename) -{ - if (!filename) - { - return nullptr; - } - - // if filename is absolute path, return the same. - if (vtksys::SystemTools::FileExists(filename)) - { - return vtksys::SystemTools::DuplicateString(filename); - } - - // Fetch any runtime defined user paths for materials - std::vector paths; - std::string userpaths; - vtksys::SystemTools::GetEnv("USER_MATERIALS_DIRS", userpaths); - if (userpaths.size() > 0) - { - vtksys::SystemTools::Split(userpaths.c_str(), paths, ';'); - } - -#ifdef VTK_MATERIALS_DIRS - // search thru default paths to locate file. - vtksys::SystemTools::Split(VTK_MATERIALS_DIRS, paths, ';'); -#endif - for (unsigned int i = 0; i < paths.size(); i++) - { - std::string path = paths[i]; - if (path.size() == 0) - { - continue; - } - vtksys::SystemTools::ConvertToUnixSlashes(path); - if (path[path.size() - 1] != '/') - { - path += "/"; - } - path += filename; - if (vtksys::SystemTools::FileExists(path.c_str())) - { - return vtksys::SystemTools::DuplicateString(path.c_str()); - } - } - return nullptr; -} - -//----------------------------------------------------------------------------- -int vtkXMLShader::GetScope() -{ - if (this->RootElement) - { - const char *scope = this->RootElement->GetAttribute("scope"); - if (!scope) - { - vtkErrorMacro("Shader description missing \"scope\" attribute."); - } - else if (strcmp(scope, "Vertex") == 0) - { - return vtkXMLShader::SCOPE_VERTEX; - } - else if (strcmp(scope, "Fragment") == 0) - { - return vtkXMLShader::SCOPE_FRAGMENT; - } - else if (strcmp(scope, "Geometry") == 0) - { - return vtkXMLShader::SCOPE_GEOMETRY; - } - } - return vtkXMLShader::SCOPE_NONE; -} - -// ---------------------------------------------------------------------------- -// \post valid_result: result==1 || result==2 -int vtkXMLShader::GetStyle() -{ - int result = 1; - if (this->RootElement) - { - const char *loc = this->RootElement->GetAttribute("style"); - if (loc == nullptr) - { - // fine. this attribute is optional. - } - else - { - if (strcmp(loc, "1") == 0) - { - // fine. default value. - } - else - { - if (strcmp(loc, "2") == 0) - { - result = 2; // new style - } - else - { - vtkErrorMacro(<< "style number not supported. Expect 1 or 2. We force it to be 1."); - } - } - } - } - - assert("post valid_result" && (result == 1 || result == 2)); - return result; -} - -//----------------------------------------------------------------------------- -const char *vtkXMLShader::GetName() -{ - return (this->RootElement) ? this->RootElement->GetAttribute("name") : nullptr; -} - -//----------------------------------------------------------------------------- -const char *vtkXMLShader::GetEntry() -{ - return (this->RootElement) ? this->RootElement->GetAttribute("entry") : nullptr; -} - -//----------------------------------------------------------------------------- -const char **vtkXMLShader::GetArgs() -{ - this->CleanupArgs(); - if (!this->RootElement || !this->RootElement->GetAttribute("args")) - { - return nullptr; - } - - std::vector args; - vtksys::SystemTools::Split(this->RootElement->GetAttribute("args"), args, ' '); - - int i; - int size = static_cast(args.size()); - if (size == 0) - { - return nullptr; - } - this->Args = new char *[size + 1]; - for (i = 0; i < size; i++) - { - this->Args[i] = vtksys::SystemTools::DuplicateString(args[i].c_str()); - } - this->Args[size] = nullptr; - return const_cast(this->Args); -} - -//----------------------------------------------------------------------------- -const char *vtkXMLShader::GetCode() -{ - return this->RootElement->GetCharacterData(); -} - -//----------------------------------------------------------------------------- -void vtkXMLShader::CleanupArgs() -{ - if (this->Args) - { - char **a = this->Args; - while (*a) - { - delete[](*a); - a++; - } - delete[] this->Args; - this->Args = nullptr; - } -} - -//----------------------------------------------------------------------------- -void vtkXMLShader::PrintSelf(ostream &os, vtkIndent indent) -{ - this->Superclass::PrintSelf(os, indent); - os << indent << "Name: " << (this->GetName() ? this->GetName() : "(none)") << endl; - os << indent << "Scope: "; - switch (this->GetScope()) - { - case SCOPE_NONE: - os << "None"; - break; - case SCOPE_MIXED: - os << "Mixed"; - break; - case SCOPE_VERTEX: - os << "Vertex"; - break; - case SCOPE_FRAGMENT: - os << "Fragment"; - break; - case SCOPE_GEOMETRY: - os << "Geometry"; - break; - } - os << endl; - - os << indent << "Entry: " << (this->GetEntry() ? this->GetEntry() : "(none)") << endl; - os << indent << "Args: "; - const char **args = this->GetArgs(); - if (!args) - { - os << "(none)" << endl; - } - else - { - while (*args) - { - os << indent << *args << " "; - args++; - } - os << endl; - } - - os << indent << "RootElement: "; - if (this->RootElement) - { - os << endl; - this->RootElement->PrintSelf(os, indent.GetNextIndent()); - } - else - { - os << "(none)" << endl; - } -} diff --git a/Modules/VtkShaders/src/vtkXMLShader.h b/Modules/VtkShaders/src/vtkXMLShader.h deleted file mode 100644 index 2e08590882..0000000000 --- a/Modules/VtkShaders/src/vtkXMLShader.h +++ /dev/null @@ -1,129 +0,0 @@ -/*=================================================================== - -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. - -===================================================================*/ - -/*========================================================================= - - Program: Visualization Toolkit - Module: vtkXMLShader.h - - Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen - All rights reserved. - See Copyright.txt or http://www.kitware.com/Copyright.htm for details. - - This software is distributed WITHOUT ANY WARRANTY; without even - the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the above copyright notice for more information. - -=========================================================================*/ -// .NAME vtkXMLShader - encapsulates a Shader XML description. -// .SECTION Description -// vtkXMLShader encapsulates the XML description for a Shader. -// It provides convenient access to various attributes/properties -// of a shader. -// .SECTION Thanks -// Shader support in VTK includes key contributions by Gary Templet at -// Sandia National Labs. - -#ifndef __vtkXMLShader_h -#define __vtkXMLShader_h - -#include "vtkObject.h" -#include "vtkRenderingCoreModule.h" // For export macro - -class vtkXMLDataElement; - -class vtkXMLShader : public vtkObject -{ -public: - static vtkXMLShader *New(); - vtkTypeMacro(vtkXMLShader, vtkObject); - void PrintSelf(ostream &os, vtkIndent indent) override; - - // Description: - // Get/Set the XML root element that describes this shader. - vtkGetObjectMacro(RootElement, vtkXMLDataElement); - void SetRootElement(vtkXMLDataElement *); - - // Description: - // Returns the type of the shader as defined in the XML description. - int GetScope(); - - // Description: - // Returns the style of the shader as optionaly defined in the XML - // description. If not present, default style is 1. "style=2" means it is - // a shader without a main(). In style 2, the "main" function for the vertex - // shader part is void propFuncVS(void), the main function for the fragment - // shader part is void propFuncFS(). This is useful when combining a shader - // at the actor level and a shader defines at the renderer level, like - // the depth peeling pass. - // \post valid_result: result==1 || result==2 - int GetStyle(); - - // Description: - // Get the name of the Shader. - const char *GetName(); - - // Description: - // Get the entry point to the shader code as defined in the XML. - const char *GetEntry(); - - // Description: - // Get the shader code. - const char *GetCode(); - - // Description: - // Returns an null terminate array of the pointers to space sepatared Args - // defined in the XML description. - const char **GetArgs(); - - // Description: - // Searches the file in the VTK_MATERIALS_DIRS. - // Note that this allocates new memory for the string. - // The caller must delete it. - static char *LocateFile(const char *filename); - - // BTX - - enum ScopeCodes - { - SCOPE_NONE = 0, - SCOPE_MIXED, - SCOPE_VERTEX, - SCOPE_FRAGMENT, - SCOPE_GEOMETRY - }; - - // ETX -protected: - vtkXMLShader(); - ~vtkXMLShader(); - - char *Code; // cache for the code. - vtkSetStringMacro(Code); - - vtkXMLDataElement *RootElement; - vtkXMLDataElement *SourceLibraryElement; - void SetSourceLibraryElement(vtkXMLDataElement *); - - char **Args; - void CleanupArgs(); - -private: - vtkXMLShader(const vtkXMLShader &); // Not implemented. - void operator=(const vtkXMLShader &); // Not implemented. -}; - -#endif diff --git a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizer.h b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizer.h index 265bf49572..0b77184264 100644 --- a/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizer.h +++ b/Plugins/org.mitk.gui.qt.dosevisualization/src/internal/RTDoseVisualizer.h @@ -1,171 +1,169 @@ /*=================================================================== 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 RTDoseVisualizer_h #define RTDoseVisualizer_h #include #include #include #include "ui_RTDoseVisualizerControls.h" #include #include #include "mitkDoseVisPreferenceHelper.h" // Shader #include -#include -#include #include #include #include #include #include /*forward declarations*/ class QmitkIsoDoseLevelSetModel; class QmitkDoseColorDelegate; class QmitkDoseValueDelegate; class QmitkDoseVisualStyleDelegate; class ctkEvent; /** \brief RTDoseVisualizer \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ class RTDoseVisualizer : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: RTDoseVisualizer(); virtual ~RTDoseVisualizer(); static const std::string VIEW_ID; void OnSliceChanged(itk::Object *sender, const itk::EventObject &e); protected slots: void OnAddFreeValueClicked(); void OnRemoveFreeValueClicked(); void OnUsePrescribedDoseClicked(); void OnDataChangedInIsoLevelSetView(); void OnAbsDoseToggled(bool); void OnGlobalVisColorWashToggled(bool); void OnGlobalVisIsoLineToggled(bool); void OnShowContextMenuIsoSet(const QPoint&); void OnCurrentPresetChanged(const QString&); void OnReferenceDoseChanged(double); void OnHandleCTKEventReferenceDoseChanged(const ctkEvent& event); void OnHandleCTKEventPresetsChanged(const ctkEvent& event); void OnHandleCTKEventGlobalVisChanged(const ctkEvent& event); void ActualizeFreeIsoLine(); void OnDoseClicked(); protected: virtual void CreateQtPartControl(QWidget *parent); virtual void SetFocus(); /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, const QList& nodes ); /** Update the transfer funtion property for the color wash*/ void UpdateColorWashTransferFunction(); /** Method updates the list widget according to the current free iso values.*/ void UpdateFreeIsoValues(); /** Update the members according to the currently selected node */ void UpdateBySelectedNode(); /** Update the member widgets according to the information stored in the application preferences*/ void UpdateByPreferences(); /**helper function that iterates throug all data nodes and sets there iso level set property according to the selected preset. @TODO: should be moved outside the class, to be available for other classes at well.*/ void ActualizeIsoLevelsForAllDoseDataNodes(); /**helper function that iterates throug all data nodes and sets there reference dose value according to the preference. @TODO: should be moved outside the class, to be available for other classes at well.*/ void ActualizeReferenceDoseForAllDoseDataNodes(); /**helper function that iterates through all data nodes and sets there dose display style (relative/absolute) according to the preference. @TODO: should be moved outside the class, to be available for other classes at well.*/ void ActualizeDisplayStyleForAllDoseDataNodes(); void NodeRemoved(const mitk::DataNode* node) override; void NodeChanged(const mitk::DataNode *node) override; Ui::RTDoseVisualizerControls m_Controls; mitk::DataNode::Pointer m_selectedNode; unsigned int m_freeIsoValuesCount; mitk::PresetMapType m_Presets; std::string m_selectedPresetName; /** Prescribed Dose of the selected data.*/ mitk::DoseValueAbs m_PrescribedDose_Data; QmitkIsoDoseLevelSetModel* m_LevelSetModel; QmitkDoseColorDelegate* m_DoseColorDelegate; QmitkDoseValueDelegate* m_DoseValueDelegate; QmitkDoseVisualStyleDelegate* m_DoseVisualDelegate; bool m_internalUpdate; private: mitk::DataNode::Pointer GetIsoDoseNode(mitk::DataNode::Pointer doseNode); bool ModalityIsRTDose(const mitk::DataNode* dataNode) const; }; #endif // RTDoseVisualizer_h diff --git a/Plugins/org.mitk.gui.qt.materialeditor/src/internal/QmitkMITKSurfaceMaterialEditorView.cpp b/Plugins/org.mitk.gui.qt.materialeditor/src/internal/QmitkMITKSurfaceMaterialEditorView.cpp index f4ec9a943c..1840d78368 100644 --- a/Plugins/org.mitk.gui.qt.materialeditor/src/internal/QmitkMITKSurfaceMaterialEditorView.cpp +++ b/Plugins/org.mitk.gui.qt.materialeditor/src/internal/QmitkMITKSurfaceMaterialEditorView.cpp @@ -1,249 +1,245 @@ /*=================================================================== 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 "QmitkMITKSurfaceMaterialEditorView.h" #include "mitkBaseRenderer.h" #include "mitkNodePredicateDataType.h" #include "mitkProperties.h" #include "mitkIDataStorageService.h" #include "mitkDataNodeObject.h" #include "berryIEditorPart.h" #include "berryIWorkbenchPage.h" -#include "mitkShaderProperty.h" - #include "QmitkDataStorageComboBox.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mitkStandaloneDataStorage.h" const std::string QmitkMITKSurfaceMaterialEditorView::VIEW_ID = "org.mitk.views.mitksurfacematerialeditor"; QmitkMITKSurfaceMaterialEditorView::QmitkMITKSurfaceMaterialEditorView() : QmitkAbstractView(), m_Controls(nullptr) { fixedProperties.push_back( "shader" ); fixedProperties.push_back( "material.representation" ); fixedProperties.push_back( "color" ); fixedProperties.push_back( "opacity" ); fixedProperties.push_back( "material.wireframeLineWidth" ); fixedProperties.push_back( "material.ambientCoefficient" ); fixedProperties.push_back( "material.diffuseCoefficient" ); fixedProperties.push_back( "material.ambientColor" ); fixedProperties.push_back( "material.diffuseColor" ); fixedProperties.push_back( "material.specularColor" ); fixedProperties.push_back( "material.specularCoefficient" ); fixedProperties.push_back( "material.specularPower" ); fixedProperties.push_back( "material.interpolation" ); shaderProperties.push_back( "shader" ); shaderProperties.push_back( "material.representation" ); shaderProperties.push_back( "color" ); shaderProperties.push_back( "opacity" ); shaderProperties.push_back( "material.wireframeLineWidth" ); observerAllocated = false; } QmitkMITKSurfaceMaterialEditorView::~QmitkMITKSurfaceMaterialEditorView() { } void QmitkMITKSurfaceMaterialEditorView::InitPreviewWindow() { usedTimer=0; vtkSphereSource* sphereSource = vtkSphereSource::New(); sphereSource->SetThetaResolution(25); sphereSource->SetPhiResolution(25); sphereSource->Update(); vtkPolyData* sphere = sphereSource->GetOutput(); m_Surface = mitk::Surface::New(); m_Surface->SetVtkPolyData( sphere ); m_DataNode = mitk::DataNode::New(); m_DataNode->SetData( m_Surface ); m_DataTree = mitk::StandaloneDataStorage::New(); m_DataTree->Add( m_DataNode , (mitk::DataNode *)0 ); m_Controls->m_PreviewRenderWindow->GetRenderer()->SetDataStorage( m_DataTree ); m_Controls->m_PreviewRenderWindow->GetRenderer()->SetMapperID( mitk::BaseRenderer::Standard3D ); sphereSource->Delete(); } void QmitkMITKSurfaceMaterialEditorView::RefreshPropertiesList() { mitk::DataNode* SrcND = m_SelectedDataNode; mitk::DataNode* DstND = m_DataNode; mitk::PropertyList* DstPL = DstND->GetPropertyList(); m_Controls->m_ShaderPropertyList->SetPropertyList( 0 ); DstPL->Clear(); if(observerAllocated) { observedProperty->RemoveObserver( observerIndex ); observerAllocated=false; } if(SrcND) { mitk::PropertyList* SrcPL = SrcND->GetPropertyList(); - mitk::ShaderProperty::Pointer shaderEnum = dynamic_cast(SrcPL->GetProperty("shader")); - std::string shaderState = "fixed"; - if(shaderEnum.IsNotNull()) - { - shaderState = shaderEnum->GetValueAsString(); +// if(shaderEnum.IsNotNull()) +// { +// shaderState = shaderEnum->GetValueAsString(); - itk::MemberCommand::Pointer propertyModifiedCommand = itk::MemberCommand::New(); - propertyModifiedCommand->SetCallbackFunction(this, &QmitkMITKSurfaceMaterialEditorView::shaderEnumChange); - observerIndex = shaderEnum->AddObserver(itk::ModifiedEvent(), propertyModifiedCommand); - observedProperty = shaderEnum; - observerAllocated=true; - } +// itk::MemberCommand::Pointer propertyModifiedCommand = itk::MemberCommand::New(); +// propertyModifiedCommand->SetCallbackFunction(this, &QmitkMITKSurfaceMaterialEditorView::shaderEnumChange); +// observerIndex = shaderEnum->AddObserver(itk::ModifiedEvent(), propertyModifiedCommand); +// observedProperty = shaderEnum; +// observerAllocated=true; +// } MITK_INFO << "PROPERTIES SCAN BEGIN"; for(mitk::PropertyList::PropertyMap::const_iterator it=SrcPL->GetMap()->begin(); it!=SrcPL->GetMap()->end(); it++) { std::string name=it->first; mitk::BaseProperty *p=it->second; // MITK_INFO << "property '" << name << "' found"; if(shaderState.compare("fixed")==0) { if(std::find(fixedProperties.begin(), fixedProperties.end(), name) != fixedProperties.end()) { DstPL->SetProperty(name,p); } } else { //if(std::find(shaderProperties.begin(), shaderProperties.end(), name) != shaderProperties.end()) { DstPL->SetProperty(name,p); } } } MITK_INFO << "PROPERTIES SCAN END"; } m_Controls->m_ShaderPropertyList->SetPropertyList( DstPL ); //m_Controls->m_PreviewRenderWindow->GetRenderer()->GetVtkRenderer()->ResetCameraClippingRange(); } void QmitkMITKSurfaceMaterialEditorView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkMITKSurfaceMaterialEditorViewControls; m_Controls->setupUi(parent); this->CreateConnections(); InitPreviewWindow(); RefreshPropertiesList(); } } void QmitkMITKSurfaceMaterialEditorView::SetFocus() { m_Controls->m_ShaderPropertyList->setFocus(); } void QmitkMITKSurfaceMaterialEditorView::CreateConnections() { } void QmitkMITKSurfaceMaterialEditorView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { if(!nodes.empty()) { m_SelectedDataNode = nodes.at(0); MITK_INFO << "Node '" << m_SelectedDataNode->GetName() << "' selected"; SurfaceSelected(); } } void QmitkMITKSurfaceMaterialEditorView::SurfaceSelected() { postRefresh(); } void QmitkMITKSurfaceMaterialEditorView::shaderEnumChange(const itk::Object * /*caller*/, const itk::EventObject & /*event*/) { postRefresh(); } void QmitkMITKSurfaceMaterialEditorView::postRefresh() { if(usedTimer) return; usedTimer=startTimer(0); } void QmitkMITKSurfaceMaterialEditorView::timerEvent( QTimerEvent *e ) { if(usedTimer!=e->timerId()) { MITK_ERROR << "INTERNAL ERROR: usedTimer[" << usedTimer << "] != timerId[" << e->timerId() << "]"; } if(usedTimer) { killTimer(usedTimer); usedTimer=0; } RefreshPropertiesList(); } diff --git a/Plugins/org.mitk.gui.qt.materialeditor/src/internal/QmitkMITKSurfaceMaterialEditorView.h b/Plugins/org.mitk.gui.qt.materialeditor/src/internal/QmitkMITKSurfaceMaterialEditorView.h index d3e5a42d92..4df318e7b6 100644 --- a/Plugins/org.mitk.gui.qt.materialeditor/src/internal/QmitkMITKSurfaceMaterialEditorView.h +++ b/Plugins/org.mitk.gui.qt.materialeditor/src/internal/QmitkMITKSurfaceMaterialEditorView.h @@ -1,115 +1,113 @@ /*=================================================================== 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 _QMITKMITKSURFACEMATERIALEDITORVIEW_H_INCLUDED #define _QMITKMITKSURFACEMATERIALEDITORVIEW_H_INCLUDED #include #include #include #include "ui_QmitkMITKSurfaceMaterialEditorViewControls.h" /* #include #include #include #include #include #include #include "QtGui/QMenubarUpdatedEvent" */ #include "QmitkRenderWindow.h" #include "mitkCommon.h" #include "mitkDataStorage.h" #include "mitkDataNode.h" -#include "mitkShaderProperty.h" #include "mitkSurface.h" #include "vtkRenderer.h" #include "vtkTextActor.h" /*! \brief QmitkMITKSurfaceMaterialEditorView */ class QmitkMITKSurfaceMaterialEditorView : public QmitkAbstractView { // this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkMITKSurfaceMaterialEditorView(); virtual ~QmitkMITKSurfaceMaterialEditorView(); virtual void CreateQtPartControl(QWidget *parent) override; /// \brief Creation of the connections of main and control widget virtual void CreateConnections(); /// /// Sets the focus to an internal widget. /// virtual void SetFocus() override; virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer part, const QList& nodes) override; protected slots: void SurfaceSelected(); protected: Ui::QmitkMITKSurfaceMaterialEditorViewControls* m_Controls; private: mitk::Surface::Pointer m_Surface; mitk::DataStorage::Pointer m_DataTree; mitk::DataNode::Pointer m_DataNode; mitk::DataNode::Pointer m_SelectedDataNode; std::list fixedProperties; std::list shaderProperties; unsigned long observerIndex; bool observerAllocated; - mitk::ShaderProperty::Pointer observedProperty; void InitPreviewWindow(); int usedTimer; void timerEvent( QTimerEvent *e ) override; void RefreshPropertiesList(); void postRefresh(); void shaderEnumChange(const itk::Object *caller, const itk::EventObject &event); berry::IStructuredSelection::ConstPointer m_CurrentSelection; }; #endif // _QMITKMITKSURFACEMATERIALEDITORVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox index 87b5e157ab..45c93fb7c7 100644 --- a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox +++ b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization.dox @@ -1,151 +1,154 @@ /** \page org_mitk_views_volumevisualization The Volume Visualization Plugin \imageMacro{QmitkVolumeVisualization_Icon.png,"Icon of the Volume Visualization Plugin",2.00} \tableofcontents \section QVV_Overview Overview The Volume Visualization Plugin is a basic tool for visualizing three dimensional medical images. MITK provides generic transfer function presets for medical CT data. These functions, that map the gray-value to color and opacity, can be interactively edited. Additionally, there are controls to quickly generate common used transfer function shapes like the threshold and bell curve to help identify a range of grey-values. \imageMacro{QmitkVolumeVisualization_Overview.png,"",16.00} \section QVV_EnableVRPage Enable Volume Rendering \subsection QVV_LoadingImage Loading an image into the application Load an image into the application by
  • dragging a file into the application window.
  • selecting file / load from the menu.
Volume Visualization imposes following restrictions on images:
  • It has to be a 3D-Image Scalar image, that means a normal CT or MRT.
  • 3D+T are supported for rendering, but the histograms are not computed.
  • Also be aware that volume visualization requires a huge amount of memory. Very large images may not work, unless you use the 64bit version.
\subsection QVV_EnableVR Enable Volumerendering \imageMacro{QmitkVolumeVisualization_Checkboxen.png,"",8.21} Select an image in datamanager and click on the checkbox left of "Volumerendering". Please be patient, while the image is prepared for rendering, which can take up to a half minute. -\subsection QVV_LODGPU The LOD & GPU checkboxes +\subsection QVV_LODGPU Dropdown menus for the rendering and blend modes -Volume Rendering requires a lot of computing resources including processor, memory and graphics card. +Two dropdown menus allow selection of rendering mode (Default, RayCast, GPU) and the blend mode (Composite, Max, Min, Avg, Add). -To run volume rendering on smaller platforms, -enable the LOD checkbox (level-of-detail rendering). -Level-of-detail first renders a lower quality preview to increase interactivity. -If the user stops to interact a normal quality rendering is issued. - -The GPU checkbox tries to use computing resources on the graphics card to accelerate volume rendering. +Any Volume Rendering mode requires a lot of computing resources including processor, memory and often also graphics card. +The Default selection usually finds the best rendering mode for the available hardware. +Alternatively, it is possible to manually specify the selections RayCast and GPU. +The RayCast selection is based on CPU computation and therefore typically slow, but allows to render without hardware acceleration. +The GPU selection uses computing resources on the graphics card to accelerate volume rendering. It requires a powerful graphics card and OpenGL hardware support for shaders, but achieves much higher frame rates than software-rendering. +Blend modes define how the volume voxels intersected by the rendering rays are pooled. The composite mode specifies standard volume rendering, +for which each voxel contributes equally with opacity and color. Other blend modes simply visualize the voxel of maximum / +minimum intensity and average / add the intentities along the rendering ray. + \section QVV_PresetPage Applying premade presets \subsection QVV_Preset Internal presets There are some internal presets given, that can be used with normal CT data (given in Houndsfield units). A large set of medical data has been tested with that presets, but it may not suit on some special cases. Click on the "Preset" tab for using internal or custom presets. \imageMacro{QmitkVolumeVisualization_InternalPresets.png,"",8.30}
  • "CT Generic" is the default transferfunction that is first applied.
  • "CT Black&White" does not use any colors, as it may be distracting on some data.
  • "CT Cardiac" tries to increase detail on CTs from the heart.
  • "CT Bone" emphasizes bones and shows other areas more transparent.
  • "CT Bone (Gradient)" is like "CT Bone", but shows from other organs only the surface by using the gradient.
  • "MR Generic" is the default transferfunction that we use on MRT data (which is not normalized like CT data).
  • "CT Thorax small" tries to increase detail.
  • "CT Thorax large" tries to increase detail.
\subsection QVV_CustomPreset Saving and loading custom presets After creating or editing a transferfunction (see \ref QVV_Editing or \ref QVV_ThresholdBell), the custom transferfunction can be stored and later retrieved on the filesystem. Click "Save" (respectively "Load") button to save (load) the threshold-, color- and gradient function combined in a single .xml file. \section QVV_ThresholdBell Interactively create transferfunctions Beside the possibility to directly edit the transferfunctions (\ref QVV_Editing), a one-click generation of two commonly known shapes is given. Both generators have two parameters, that can be modified by first clicking on the cross and then moving the mouse up/down and left/right. The first parameter "center" (controlled by horizontal movement of the mouse) specifies the gravalue where the center of the shape will be located. The second parameter "width" (controlled by vertical movement of the mouse) specifies the width (or steepness) of the shape. \subsection Threshold Click on the "Threshold" tab to active the threshold function generator. \imageMacro{QmitkVolumeVisualization_Threshold.png,"",8.21} A threshold shape begins with zero and raises to one across the "center" parameter. Lower widths results in steeper threshold functions. \subsection Bell Click on the "Bell" tab to active the threshold function generator. \imageMacro{QmitkVolumeVisualization_Bell.png,"",8.23} A threshold shape begins with zero and raises to one at the "center" parameter and the lowers agains to zero. The "width" parameter correspondens to the width of the bell. \section QVV_Editing Customize transferfunctions in detail \subsection QVV_Navigate Choosing grayvalue interval to edit \imageMacro{QmitkVolumeVisualization_Slider.png,"",8.23} To navigate across the grayvalue range or to zoom in some ranges use the "range"-slider. All three function editors have in common following:
  • By left-clicking a new point is added.
  • By right-clicking a point is deleted.
  • By left-clicking and holding, an exisiting point can be dragged.
  • By pressing arrow keys, the currently selected point is moved.
  • By pressing the "DELETE" key, the currently selected point is deleted.
  • Between points the transferfunctions are linear interpolated.
There are three transferfunctions to customize: \subsection QVV_GO Grayvalue -> Opacity \imageMacro{QmitkVolumeVisualization_Opacity.png,"grayvalues will be mapped to opacity.",8.04} An opacity of 0 means total transparent, an opacity of 1 means total opaque. \subsection QVV_GC Grayvalue -> Color \imageMacro{QmitkVolumeVisualization_Color.png,"grayvalues will be mapped to color.",8.81} The color transferfunction editor also allows by double-clicking a point to change its color. \subsection QVV_GGO Grayvalue and Gradient -> Opacity \imageMacro{QmitkVolumeVisualization_Gradient.png,"",8.85} Here the influence of the gradient is controllable at specific grayvalues. */ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Checkboxen.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Checkboxen.png index 473bdcf868..31f968a1ac 100644 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Checkboxen.png and b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Checkboxen.png differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Overview.png b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Overview.png index 495e19e807..70621fbd52 100644 Binary files a/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Overview.png and b/Plugins/org.mitk.gui.qt.volumevisualization/documentation/UserManual/QmitkVolumeVisualization_Overview.png differ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp index f6ab96e5b9..8dc1efe285 100755 --- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp +++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.cpp @@ -1,350 +1,344 @@ /*=================================================================== 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 "QmitkVolumeVisualizationView.h" #include #include +#include #include #include #include //#include #include #include #include #include #include #include #include "mitkHistogramGenerator.h" #include "QmitkPiecewiseFunctionCanvas.h" #include "QmitkColorTransferFunctionCanvas.h" #include "mitkBaseRenderer.h" #include "mitkVtkVolumeRenderingProperty.h" #include #include const std::string QmitkVolumeVisualizationView::VIEW_ID = "org.mitk.views.volumevisualization"; -enum RenderMode -{ - RM_CPU_COMPOSITE_RAYCAST = 0, - RM_CPU_MIP_RAYCAST = 1, - RM_GPU_COMPOSITE_SLICING = 2, - RM_GPU_COMPOSITE_RAYCAST = 3, - RM_GPU_MIP_RAYCAST = 4 -}; +enum {DEFAULT_RENDERMODE = 0, RAYCAST_RENDERMODE = 1, GPU_RENDERMODE = 2}; QmitkVolumeVisualizationView::QmitkVolumeVisualizationView() : QmitkAbstractView(), m_Controls(nullptr) { } QmitkVolumeVisualizationView::~QmitkVolumeVisualizationView() { } void QmitkVolumeVisualizationView::CreateQtPartControl(QWidget* parent) { if (!m_Controls) { m_Controls = new Ui::QmitkVolumeVisualizationViewControls; m_Controls->setupUi(parent); // Fill the tf presets in the generator widget std::vector names; mitk::TransferFunctionInitializer::GetPresetNames(names); for (std::vector::const_iterator it = names.begin(); it != names.end(); ++it) { m_Controls->m_TransferFunctionGeneratorWidget->AddPreset(QString::fromStdString(*it)); } - - m_Controls->m_RenderMode->addItem("CPU raycast"); - m_Controls->m_RenderMode->addItem("CPU MIP raycast"); - m_Controls->m_RenderMode->addItem("GPU slicing"); -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) - m_Controls->m_RenderMode->addItem("GPU raycast"); - m_Controls->m_RenderMode->addItem("GPU MIP raycast"); -#endif + + // see enum in vtkSmartVolumeMapper + m_Controls->m_RenderMode->addItem("Default"); + m_Controls->m_RenderMode->addItem("RayCast"); + m_Controls->m_RenderMode->addItem("GPU"); + + // see vtkVolumeMapper::BlendModes + m_Controls->m_BlendMode->addItem("Comp"); + m_Controls->m_BlendMode->addItem("Max"); + m_Controls->m_BlendMode->addItem("Min"); + m_Controls->m_BlendMode->addItem("Avg"); + m_Controls->m_BlendMode->addItem("Add"); connect( m_Controls->m_EnableRenderingCB, SIGNAL( toggled(bool) ),this, SLOT( OnEnableRendering(bool) )); - connect( m_Controls->m_EnableLOD, SIGNAL( toggled(bool) ),this, SLOT( OnEnableLOD(bool) )); - connect( m_Controls->m_RenderMode, SIGNAL( activated(int) ),this, SLOT( OnRenderMode(int) )); + connect(m_Controls->m_RenderMode, SIGNAL(activated(int)), this, SLOT(OnRenderMode(int))); + connect(m_Controls->m_BlendMode, SIGNAL(activated(int)), this, SLOT(OnBlendMode(int))); connect( m_Controls->m_TransferFunctionGeneratorWidget, SIGNAL( SignalUpdateCanvas( ) ), m_Controls->m_TransferFunctionWidget, SLOT( OnUpdateCanvas( ) ) ); connect( m_Controls->m_TransferFunctionGeneratorWidget, SIGNAL(SignalTransferFunctionModeChanged(int)), SLOT(OnMitkInternalPreset(int))); m_Controls->m_EnableRenderingCB->setEnabled(false); - m_Controls->m_EnableLOD->setEnabled(false); + m_Controls->m_BlendMode->setEnabled(false); m_Controls->m_RenderMode->setEnabled(false); m_Controls->m_TransferFunctionWidget->setEnabled(false); m_Controls->m_TransferFunctionGeneratorWidget->setEnabled(false); m_Controls->m_SelectedImageLabel->hide(); m_Controls->m_ErrorImageLabel->hide(); - } } void QmitkVolumeVisualizationView::OnMitkInternalPreset( int mode ) { if (m_SelectedNode.IsNull()) return; mitk::DataNode::Pointer node(m_SelectedNode.GetPointer()); mitk::TransferFunctionProperty::Pointer transferFuncProp; if (node->GetProperty(transferFuncProp, "TransferFunction")) { //first item is only information if( --mode == -1 ) return; // -- Creat new TransferFunction mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(transferFuncProp->GetValue()); tfInit->SetTransferFunctionMode(mode); RequestRenderWindowUpdate(); m_Controls->m_TransferFunctionWidget->OnUpdateCanvas(); } } void QmitkVolumeVisualizationView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*part*/, const QList& nodes) { bool weHadAnImageButItsNotThreeDeeOrFourDee = false; mitk::DataNode::Pointer node; for (mitk::DataNode::Pointer currentNode: nodes) { if( currentNode.IsNotNull() && dynamic_cast(currentNode->GetData()) ) { if( dynamic_cast(currentNode->GetData())->GetDimension()>=3 ) { if (node.IsNull()) { node = currentNode; } } else { weHadAnImageButItsNotThreeDeeOrFourDee = true; } } } if( node.IsNotNull() ) { m_Controls->m_NoSelectedImageLabel->hide(); m_Controls->m_ErrorImageLabel->hide(); m_Controls->m_SelectedImageLabel->show(); std::string infoText; if (node->GetName().empty()) infoText = std::string("Selected Image: [currently selected image has no name]"); else infoText = std::string("Selected Image: ") + node->GetName(); m_Controls->m_SelectedImageLabel->setText( QString( infoText.c_str() ) ); m_SelectedNode = node; } else { if(weHadAnImageButItsNotThreeDeeOrFourDee) { m_Controls->m_NoSelectedImageLabel->hide(); m_Controls->m_ErrorImageLabel->show(); std::string infoText; infoText = std::string("only 3D or 4D images are supported"); m_Controls->m_ErrorImageLabel->setText( QString( infoText.c_str() ) ); } else { m_Controls->m_SelectedImageLabel->hide(); m_Controls->m_ErrorImageLabel->hide(); m_Controls->m_NoSelectedImageLabel->show(); } m_SelectedNode = 0; } UpdateInterface(); } void QmitkVolumeVisualizationView::UpdateInterface() { if(m_SelectedNode.IsNull()) { // turnoff all m_Controls->m_EnableRenderingCB->setChecked(false); m_Controls->m_EnableRenderingCB->setEnabled(false); - m_Controls->m_EnableLOD->setChecked(false); - m_Controls->m_EnableLOD->setEnabled(false); + m_Controls->m_BlendMode->setCurrentIndex(0); + m_Controls->m_BlendMode->setEnabled(false); m_Controls->m_RenderMode->setCurrentIndex(0); m_Controls->m_RenderMode->setEnabled(false); m_Controls->m_TransferFunctionWidget->SetDataNode(0); m_Controls->m_TransferFunctionWidget->setEnabled(false); m_Controls->m_TransferFunctionGeneratorWidget->SetDataNode(0); m_Controls->m_TransferFunctionGeneratorWidget->setEnabled(false); return; } bool enabled = false; m_SelectedNode->GetBoolProperty("volumerendering",enabled); m_Controls->m_EnableRenderingCB->setEnabled(true); m_Controls->m_EnableRenderingCB->setChecked(enabled); if(!enabled) { // turnoff all except volumerendering checkbox - m_Controls->m_EnableLOD->setChecked(false); - m_Controls->m_EnableLOD->setEnabled(false); + m_Controls->m_BlendMode->setCurrentIndex(0); + m_Controls->m_BlendMode->setEnabled(false); m_Controls->m_RenderMode->setCurrentIndex(0); m_Controls->m_RenderMode->setEnabled(false); m_Controls->m_TransferFunctionWidget->SetDataNode(0); m_Controls->m_TransferFunctionWidget->setEnabled(false); m_Controls->m_TransferFunctionGeneratorWidget->SetDataNode(0); m_Controls->m_TransferFunctionGeneratorWidget->setEnabled(false); return; } // otherwise we can activate em all - enabled = false; - m_SelectedNode->GetBoolProperty("volumerendering.uselod",enabled); - m_Controls->m_EnableLOD->setEnabled(true); - m_Controls->m_EnableLOD->setChecked(enabled); - + m_Controls->m_BlendMode->setEnabled(true); m_Controls->m_RenderMode->setEnabled(true); // Determine Combo Box mode { bool usegpu=false; bool useray=false; bool usemip=false; m_SelectedNode->GetBoolProperty("volumerendering.usegpu",usegpu); -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) m_SelectedNode->GetBoolProperty("volumerendering.useray",useray); -#endif m_SelectedNode->GetBoolProperty("volumerendering.usemip",usemip); + + int blendMode; + if (m_SelectedNode->GetIntProperty("volumerendering.blendmode", blendMode)) + m_Controls->m_BlendMode->setCurrentIndex(blendMode); - int mode = 0; + if (usemip) + m_Controls->m_BlendMode->setCurrentIndex(vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND); - if(useray) - { - if(usemip) - mode=RM_GPU_MIP_RAYCAST; - else - mode=RM_GPU_COMPOSITE_RAYCAST; - } - else if(usegpu) - mode=RM_GPU_COMPOSITE_SLICING; - else - { - if(usemip) - mode=RM_CPU_MIP_RAYCAST; - else - mode=RM_CPU_COMPOSITE_RAYCAST; - } + int mode = DEFAULT_RENDERMODE; + if (useray) + mode = RAYCAST_RENDERMODE; + else if(usegpu) + mode = GPU_RENDERMODE; + m_Controls->m_RenderMode->setCurrentIndex(mode); + } m_Controls->m_TransferFunctionWidget->SetDataNode(m_SelectedNode); m_Controls->m_TransferFunctionWidget->setEnabled(true); m_Controls->m_TransferFunctionGeneratorWidget->SetDataNode(m_SelectedNode); m_Controls->m_TransferFunctionGeneratorWidget->setEnabled(true); } void QmitkVolumeVisualizationView::OnEnableRendering(bool state) { if(m_SelectedNode.IsNull()) return; m_SelectedNode->SetProperty("volumerendering",mitk::BoolProperty::New(state)); UpdateInterface(); RequestRenderWindowUpdate(); } -void QmitkVolumeVisualizationView::OnEnableLOD(bool state) +void QmitkVolumeVisualizationView::OnBlendMode(int mode) { - if(m_SelectedNode.IsNull()) + if (m_SelectedNode.IsNull()) return; - m_SelectedNode->SetProperty("volumerendering.uselod",mitk::BoolProperty::New(state)); + bool usemip = false; + if (mode == vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND) + usemip = true; + + m_SelectedNode->SetProperty("volumerendering.usemip", mitk::BoolProperty::New(usemip)); + m_SelectedNode->SetProperty("volumerendering.blendmode", mitk::IntProperty::New(mode)); + RequestRenderWindowUpdate(); } void QmitkVolumeVisualizationView::OnRenderMode(int mode) { if(m_SelectedNode.IsNull()) return; - - bool usegpu=mode==RM_GPU_COMPOSITE_SLICING; -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) - bool useray=(mode==RM_GPU_COMPOSITE_RAYCAST)||(mode==RM_GPU_MIP_RAYCAST); -#endif - bool usemip=(mode==RM_GPU_MIP_RAYCAST)||(mode==RM_CPU_MIP_RAYCAST); + + bool usegpu = false; + if (mode == GPU_RENDERMODE) + usegpu = true; + + bool useray = false; + if (mode == RAYCAST_RENDERMODE) + useray = true; + + if (mode == DEFAULT_RENDERMODE) + { + useray = true; + usegpu = true; + } m_SelectedNode->SetProperty("volumerendering.usegpu",mitk::BoolProperty::New(usegpu)); -// Only with VTK 5.6 or above -#if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) m_SelectedNode->SetProperty("volumerendering.useray",mitk::BoolProperty::New(useray)); -#endif - m_SelectedNode->SetProperty("volumerendering.usemip",mitk::BoolProperty::New(usemip)); RequestRenderWindowUpdate(); } void QmitkVolumeVisualizationView::SetFocus() { } void QmitkVolumeVisualizationView::NodeRemoved(const mitk::DataNode* node) { if(m_SelectedNode == node) { m_SelectedNode=0; m_Controls->m_SelectedImageLabel->hide(); m_Controls->m_ErrorImageLabel->hide(); m_Controls->m_NoSelectedImageLabel->show(); UpdateInterface(); } } diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h index 601a8e1009..8bd075f564 100755 --- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h +++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationView.h @@ -1,83 +1,82 @@ /*=================================================================== 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 QMITKVOLUMEVISUALIZATIONVIEW_H_ #define QMITKVOLUMEVISUALIZATIONVIEW_H_ #include #include #include #include #include "mitkDataStorage.h" #include #include #include #include "ui_QmitkVolumeVisualizationViewControls.h" /** * \ingroup org_mitk_gui_qt_volumevisualization_internal */ class QmitkVolumeVisualizationView : public QmitkAbstractView { Q_OBJECT public: void SetFocus() override; QmitkVolumeVisualizationView(); virtual ~QmitkVolumeVisualizationView(); virtual void CreateQtPartControl(QWidget *parent) override; /// /// Invoked when the DataManager selection changed /// virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList& nodes) override; static const std::string VIEW_ID; protected slots: void OnMitkInternalPreset( int mode ); void OnEnableRendering( bool state ); - void OnEnableLOD( bool state ); void OnRenderMode( int mode ); - + void OnBlendMode(int mode); protected: Ui::QmitkVolumeVisualizationViewControls* m_Controls; private: mitk::WeakPointer m_SelectedNode; void UpdateInterface(); void NodeRemoved(const mitk::DataNode* node) override; }; #endif /*QMITKVOLUMEVISUALIZATIONVIEW_H_*/ diff --git a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationViewControls.ui b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationViewControls.ui index 982bc0f0a9..2a0476f821 100644 --- a/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationViewControls.ui +++ b/Plugins/org.mitk.gui.qt.volumevisualization/src/internal/QmitkVolumeVisualizationViewControls.ui @@ -1,334 +1,327 @@ QmitkVolumeVisualizationViewControls 0 0 324 679 0 0 16777215 16777215 QmitkTemplate 0 0 191 0 0 191 0 0 191 0 0 191 0 0 191 0 0 191 0 0 120 120 120 120 120 120 120 120 120 0 0 197 0 0 191 0 0 189 0 0 197 0 0 191 0 0 189 0 0 120 120 120 120 120 120 120 120 120 Please select a volume image! 0 0 Click this checkbox to enable volumerendering in the 3D view of the selected image. Volumerendering - - - - Level of detail (LOD) enables a fast but lower quality preview rendering to increase interactivity. - - - LOD - - - 0 1 Select render mode + + + 0 0 0 0 0 1 QmitkTransferFunctionWidget QWidget
QmitkTransferFunctionWidget.h
QmitkTransferFunctionGeneratorWidget QWidget
QmitkTransferFunctionGeneratorWidget.h
1
QmitkDataStorageComboBox.h