diff --git a/Applications/PluginGenerator/ProjectTemplate/CMakeExternals/MITK.cmake b/Applications/PluginGenerator/ProjectTemplate/CMakeExternals/MITK.cmake index 43155e16cd..60fd693999 100644 --- a/Applications/PluginGenerator/ProjectTemplate/CMakeExternals/MITK.cmake +++ b/Applications/PluginGenerator/ProjectTemplate/CMakeExternals/MITK.cmake @@ -1,211 +1,211 @@ #----------------------------------------------------------------------------- # MITK #----------------------------------------------------------------------------- set(MITK_DEPENDS) set(proj_DEPENDENCIES) set(proj MITK) if(NOT MITK_DIR) #----------------------------------------------------------------------------- # Create CMake options to customize the MITK build #----------------------------------------------------------------------------- option(MITK_USE_SUPERBUILD "Use superbuild for MITK" ON) option(MITK_USE_BLUEBERRY "Build the BlueBerry platform in MITK" ON) option(MITK_BUILD_EXAMPLES "Build the MITK examples" OFF) option(MITK_BUILD_ALL_PLUGINS "Build all MITK plugins" OFF) option(MITK_BUILD_TESTING "Build the MITK unit tests" OFF) - option(MITK_USE_ACVD "Use Approximated Centroidal Voronoi Diagrams" OFF) + option(MITK_USE_OpenMesh "" OFF) option(MITK_USE_CTK "Use CTK in MITK" ${MITK_USE_BLUEBERRY}) option(MITK_USE_DCMTK "Use DCMTK in MITK" ON) option(MITK_USE_Qt5 "Use Qt 5 library in MITK" ON) option(MITK_USE_DCMQI "Use dcmqi in MITK" OFF) option(MITK_USE_OpenCV "Use Intel's OpenCV library" OFF) option(MITK_USE_Python3 "Enable Python wrapping in MITK" OFF) if(MITK_USE_BLUEBERRY AND NOT MITK_USE_CTK) message("Forcing MITK_USE_CTK to ON because of MITK_USE_BLUEBERRY") set(MITK_USE_CTK ON CACHE BOOL "Use CTK in MITK" FORCE) endif() if(MITK_USE_CTK AND NOT MITK_USE_Qt5) message("Forcing MITK_USE_Qt5 to ON because of MITK_USE_CTK") set(MITK_USE_Qt5 ON CACHE BOOL "Use Qt 5 library in MITK" FORCE) endif() set(MITK_USE_CableSwig ${MITK_USE_Python3}) set(MITK_USE_GDCM 1) set(MITK_USE_ITK 1) set(MITK_USE_VTK 1) mark_as_advanced(MITK_USE_SUPERBUILD MITK_BUILD_ALL_PLUGINS MITK_BUILD_TESTING ) set(mitk_cmake_boolean_args MITK_USE_SUPERBUILD MITK_USE_BLUEBERRY MITK_BUILD_EXAMPLES MITK_BUILD_ALL_PLUGINS - MITK_USE_ACVD + MITK_USE_OpenMesh MITK_USE_CTK MITK_USE_DCMTK MITK_USE_Qt5 MITK_USE_DCMQI MITK_USE_OpenCV MITK_USE_Python3 ) if(MITK_USE_Qt5) # Look for Qt at the superbuild level, to catch missing Qt libs early find_package(Qt5Widgets REQUIRED) endif() set(additional_mitk_cmakevars ) # Configure the set of default pixel types set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") foreach(_arg MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES MITK_ACCESSBYITK_DIMENSIONS) mark_as_advanced(${_arg}) list(APPEND additional_mitk_cmakevars "-D${_arg}:STRING=${${_arg}}") endforeach() #----------------------------------------------------------------------------- # Create options to inject pre-build dependencies #----------------------------------------------------------------------------- - foreach(proj CTK DCMTK DCMQI GDCM VTK ACVD ITK OpenCV CableSwig) + foreach(proj CTK DCMTK DCMQI GDCM VTK OpenMesh ITK OpenCV CableSwig) if(MITK_USE_${proj}) set(MITK_${proj}_DIR "${${proj}_DIR}" CACHE PATH "Path to ${proj} build directory") mark_as_advanced(MITK_${proj}_DIR) if(MITK_${proj}_DIR) list(APPEND additional_mitk_cmakevars "-D${proj}_DIR:PATH=${MITK_${proj}_DIR}") endif() endif() endforeach() set(MITK_BOOST_ROOT "${BOOST_ROOT}" CACHE PATH "Path to Boost directory") mark_as_advanced(MITK_BOOST_ROOT) if(MITK_BOOST_ROOT) list(APPEND additional_mitk_cmakevars "-DBOOST_ROOT:PATH=${MITK_BOOST_ROOT}") endif() set(MITK_SOURCE_DIR "" CACHE PATH "MITK source code location. If empty, MITK will be cloned from MITK_GIT_REPOSITORY") set(MITK_GIT_REPOSITORY "https://phabricator.mitk.org/source/mitk.git" CACHE STRING "The git repository for cloning MITK") set(MITK_GIT_TAG "origin/master" CACHE STRING "The git tag/hash to be used when cloning from MITK_GIT_REPOSITORY") mark_as_advanced(MITK_SOURCE_DIR MITK_GIT_REPOSITORY MITK_GIT_TAG) #----------------------------------------------------------------------------- # Create the final variable containing superbuild boolean args #----------------------------------------------------------------------------- set(mitk_boolean_args) foreach(mitk_cmake_arg ${mitk_cmake_boolean_args}) list(APPEND mitk_boolean_args -D${mitk_cmake_arg}:BOOL=${${mitk_cmake_arg}}) endforeach() #----------------------------------------------------------------------------- # Additional MITK CMake variables #----------------------------------------------------------------------------- if(MITK_USE_Qt5) list(APPEND additional_mitk_cmakevars "-DCMAKE_PREFIX_PATH:PATH=${CMAKE_PREFIX_PATH}") endif() if(MITK_USE_CTK) list(APPEND additional_mitk_cmakevars "-DGIT_EXECUTABLE:FILEPATH=${GIT_EXECUTABLE}") endif() if(MITK_INITIAL_CACHE_FILE) list(APPEND additional_mitk_cmakevars "-DMITK_INITIAL_CACHE_FILE:INTERNAL=${MITK_INITIAL_CACHE_FILE}") endif() if(MITK_USE_SUPERBUILD) set(MITK_BINARY_DIR ${proj}-superbuild) else() set(MITK_BINARY_DIR ${proj}-build) endif() set(proj_DEPENDENCIES) set(MITK_DEPENDS ${proj}) # Configure the MITK souce code location if(NOT MITK_SOURCE_DIR) set(mitk_source_location SOURCE_DIR ${CMAKE_BINARY_DIR}/${proj} GIT_REPOSITORY ${MITK_GIT_REPOSITORY} GIT_TAG ${MITK_GIT_TAG} ) else() set(mitk_source_location SOURCE_DIR ${MITK_SOURCE_DIR} ) endif() ExternalProject_Add(${proj} ${mitk_source_location} BINARY_DIR ${MITK_BINARY_DIR} PREFIX ${proj}${ep_suffix} INSTALL_COMMAND "" CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} ${mitk_boolean_args} ${additional_mitk_cmakevars} -DBUILD_SHARED_LIBS:BOOL=ON -DBUILD_TESTING:BOOL=${MITK_BUILD_TESTING} CMAKE_CACHE_ARGS ${ep_common_cache_args} CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} DEPENDS ${proj_DEPENDENCIES} ) if(MITK_USE_SUPERBUILD) set(MITK_DIR "${CMAKE_CURRENT_BINARY_DIR}/${MITK_BINARY_DIR}/MITK-build") else() set(MITK_DIR "${CMAKE_CURRENT_BINARY_DIR}/${MITK_BINARY_DIR}") endif() else() # The project is provided using MITK_DIR, nevertheless since other # projects may depend on MITK, let's add an 'empty' one MacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") # Further, do some sanity checks in the case of a pre-built MITK set(my_itk_dir ${ITK_DIR}) set(my_vtk_dir ${VTK_DIR}) find_package(MITK REQUIRED) if(my_itk_dir AND NOT my_itk_dir STREQUAL ${ITK_DIR}) message(FATAL_ERROR "ITK packages do not match:\n ${MY_PROJECT_NAME}: ${my_itk_dir}\n MITK: ${ITK_DIR}") endif() if(my_vtk_dir AND NOT my_vtk_dir STREQUAL ${VTK_DIR}) message(FATAL_ERROR "VTK packages do not match:\n ${MY_PROJECT_NAME}: ${my_vtk_dir}\n MITK: ${VTK_DIR}") endif() endif() diff --git a/CMake/BuildConfigurations/Default.cmake b/CMake/BuildConfigurations/Default.cmake index 4faffa7f12..ab92d73684 100644 --- a/CMake/BuildConfigurations/Default.cmake +++ b/CMake/BuildConfigurations/Default.cmake @@ -1,23 +1,23 @@ set(MITK_CONFIG_PACKAGES - ACVD + OpenMesh Qt5 BLUEBERRY ) set(MITK_CONFIG_PLUGINS org.mitk.gui.qt.mitkworkbench.intro org.mitk.gui.qt.datamanager org.mitk.gui.qt.stdmultiwidgeteditor org.mitk.gui.qt.dicombrowser org.mitk.gui.qt.imagenavigator org.mitk.gui.qt.measurementtoolbox org.mitk.gui.qt.properties org.mitk.gui.qt.segmentation org.mitk.gui.qt.volumevisualization org.mitk.planarfigure org.mitk.gui.qt.moviemaker org.mitk.gui.qt.pointsetinteraction org.mitk.gui.qt.remeshing org.mitk.gui.qt.viewnavigator org.mitk.gui.qt.imagecropper ) diff --git a/CMake/BuildConfigurations/mitkNavigationModules.cmake b/CMake/BuildConfigurations/mitkNavigationModules.cmake index d6881034ab..5836dc8d04 100644 --- a/CMake/BuildConfigurations/mitkNavigationModules.cmake +++ b/CMake/BuildConfigurations/mitkNavigationModules.cmake @@ -1,35 +1,35 @@ message(STATUS "Configuring MITK Navigation Modules Build") set(MITK_CONFIG_PACKAGES - ACVD + OpenMesh Qt5 BLUEBERRY ) # Enable open cv and open igt link, which is a necessary configuration set(MITK_USE_OpenCV ON CACHE BOOL "MITK Use OpenCV Library" FORCE) set(MITK_USE_OpenIGTLink ON CACHE BOOL "MITK Use OpenIGTLink Library" FORCE) # Enable default plugins and the navigation modules set(MITK_CONFIG_PLUGINS org.mitk.gui.qt.datamanager org.mitk.gui.qt.stdmultiwidgeteditor org.mitk.gui.qt.dicombrowser org.mitk.gui.qt.imagenavigator org.mitk.gui.qt.measurementtoolbox org.mitk.gui.qt.properties org.mitk.gui.qt.segmentation org.mitk.gui.qt.volumevisualization org.mitk.planarfigure org.mitk.gui.qt.moviemaker org.mitk.gui.qt.pointsetinteraction org.mitk.gui.qt.registration org.mitk.gui.qt.remeshing org.mitk.gui.qt.viewnavigator org.mitk.gui.qt.imagecropper org.mitk.gui.qt.igttracking org.mitk.gui.qt.openigtlink org.mitk.gui.qt.ultrasound org.mitk.gui.qt.tofutil ) diff --git a/CMake/PackageDepends/MITK_ACVD_Config.cmake b/CMake/PackageDepends/MITK_ACVD_Config.cmake deleted file mode 100644 index 55d36d47bf..0000000000 --- a/CMake/PackageDepends/MITK_ACVD_Config.cmake +++ /dev/null @@ -1,4 +0,0 @@ -list(APPEND ALL_LIBRARIES ${ACVD_LIBRARIES}) -if(ACVD_INCLUDE_DIRS) - list(APPEND ALL_INCLUDE_DIRECTORIES ${ACVD_INCLUDE_DIRS}) -endif() diff --git a/CMake/PackageDepends/MITK_OpenMesh_Config.cmake b/CMake/PackageDepends/MITK_OpenMesh_Config.cmake new file mode 100644 index 0000000000..e69de29bb2 diff --git a/CMake/mitkFunctionGetLibrarySearchPaths.cmake b/CMake/mitkFunctionGetLibrarySearchPaths.cmake index 86725d7193..21f2436c0e 100644 --- a/CMake/mitkFunctionGetLibrarySearchPaths.cmake +++ b/CMake/mitkFunctionGetLibrarySearchPaths.cmake @@ -1,213 +1,219 @@ #! Helper function that gets all library search paths. #! #! Usage: #! #! mitkFunctionGetLibrarySearchPaths(search_path intermediate_dir [DEBUG|MINSIZEREL|RELWITHDEBINFO]) #! #! #! The function creates the variable ${search_path}. The variable intermediate_dir contains #! paths that should be added to the search_path but should not be checked for existance, #! because the are not yet created. The option DEBUG, MINSIZEREL or RELWITHDEBINFO can be used to indicate that #! not the paths for release configuration are requested but the debug, min size release or "release with debug info" #! paths. #! function(mitkFunctionGetLibrarySearchPaths search_path intermediate_dir) cmake_parse_arguments(PARSE_ARGV 2 GLS "RELEASE;DEBUG;MINSIZEREL;RELWITHDEBINFO" "" "") set(_dir_candidates "${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins" "${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}" "${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins" ) if(MITK_EXTERNAL_PROJECT_PREFIX) list(APPEND _dir_candidates "${MITK_EXTERNAL_PROJECT_PREFIX}/bin" "${MITK_EXTERNAL_PROJECT_PREFIX}/lib" ) endif() # Determine the Qt5 library installation prefix set(_qmake_location ) if(MITK_USE_Qt5 AND TARGET ${Qt5Core_QMAKE_EXECUTABLE}) get_property(_qmake_location TARGET ${Qt5Core_QMAKE_EXECUTABLE} PROPERTY IMPORT_LOCATION) endif() if(_qmake_location) if(NOT _qt_install_libs) if(WIN32) execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_BINS OUTPUT_VARIABLE _qt_install_libs OUTPUT_STRIP_TRAILING_WHITESPACE) else() execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_LIBS OUTPUT_VARIABLE _qt_install_libs OUTPUT_STRIP_TRAILING_WHITESPACE) endif() file(TO_CMAKE_PATH "${_qt_install_libs}" _qt_install_libs) set(_qt_install_libs ${_qt_install_libs} CACHE INTERNAL "Qt library installation prefix" FORCE) endif() if(_qt_install_libs) list(APPEND _dir_candidates ${_qt_install_libs}) endif() elseif(MITK_USE_Qt5) message(WARNING "The qmake executable could not be found.") endif() get_property(_additional_paths GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) if(TARGET OpenSSL::SSL) if(GLS_DEBUG) get_target_property(_openssl_location OpenSSL::SSL IMPORTED_LOCATION_DEBUG) else() get_target_property(_openssl_location OpenSSL::SSL IMPORTED_LOCATION_RELEASE) endif() if(_openssl_location) get_filename_component(_openssl_location ${_openssl_location} DIRECTORY) set(_openssl_location "${_openssl_location}/../../bin") if(EXISTS ${_openssl_location}) get_filename_component(_openssl_location ${_openssl_location} ABSOLUTE) list(APPEND _dir_candidates ${_openssl_location}) endif() endif() endif() if(MITK_USE_HDF5) FIND_PACKAGE(HDF5 COMPONENTS C HL NO_MODULE REQUIRED shared) get_target_property(_location hdf5-shared LOCATION) get_filename_component(_location ${_location} PATH) list(APPEND _additional_paths ${_location}) # This is a work-around. The hdf5-config.cmake file is not robust enough # to be included several times via find_pakcage calls. set(HDF5_LIBRARIES ${HDF5_LIBRARIES} PARENT_SCOPE) endif() if(MITK_USE_Vigra) # we cannot use _find_package(Vigra) here because the vigra-config.cmake file # always includes the target-exports files without using an include guard. This # would lead to errors when another find_package(Vigra) call is processed. The # (bad) assumption here is that for the time being, only the Classification module # is using Vigra. if(UNIX) list(APPEND _additional_paths ${Vigra_DIR}/lib) else() list(APPEND _additional_paths ${Vigra_DIR}/bin) endif() endif() if(_additional_paths) list(APPEND _dir_candidates ${_additional_paths}) endif() # The code below is sub-optimal. It makes assumptions about # the structure of the build directories, pointed to by # the *_DIR variables. Instead, we should rely on package # specific "LIBRARY_DIRS" variables, if they exist. if(WIN32) list(APPEND _dir_candidates "${ITK_DIR}/bin") endif() if(MITK_USE_MatchPoint) if(WIN32) list(APPEND _dir_candidates "${MatchPoint_DIR}/bin") else() list(APPEND _dir_candidates "${MatchPoint_DIR}/lib") endif() endif() # If OpenCV is built within the MITK superbuild set the binary directory # according to the lib path provided by OpenCV. # In the case where an external OpenCV is provided use the binary directory # of this OpenCV directory if(MITK_USE_OpenCV) if(WIN32) if (EXISTS ${OpenCV_LIB_PATH}) list(APPEND _dir_candidates "${OpenCV_LIB_PATH}/../bin") # OpenCV is built in superbuild else() list(APPEND _dir_candidates "${OpenCV_DIR}/bin") # External OpenCV build is used endif() endif() endif() + if(MITK_USE_OpenMesh) + if(WIN32) + list(APPEND _dir_candidates "${MITK_EXTERNAL_PROJECT_PREFIX}") + endif() + endif() + if(MITK_USE_Python3) list(APPEND _dir_candidates "${CTK_DIR}/CMakeExternals/Install/bin") get_filename_component(_python_dir "${Python3_EXECUTABLE}" DIRECTORY) list(APPEND _dir_candidates "${_python_dir}") endif() if(MITK_USE_TOF_PMDO3 OR MITK_USE_TOF_PMDCAMCUBE OR MITK_USE_TOF_PMDCAMBOARD) list(APPEND _dir_candidates "${MITK_PMD_SDK_DIR}/plugins" "${MITK_PMD_SDK_DIR}/bin") endif() if(MITK_USE_CTK) list(APPEND _dir_candidates "${CTK_LIBRARY_DIRS}") foreach(_ctk_library ${CTK_LIBRARIES}) if(${_ctk_library}_LIBRARY_DIRS) list(APPEND _dir_candidates "${${_ctk_library}_LIBRARY_DIRS}") endif() endforeach() endif() if(MITK_USE_BLUEBERRY) if(DEFINED CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY) if(IS_ABSOLUTE "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") list(APPEND _dir_candidates "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") else() list(APPEND _dir_candidates "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") endif() endif() endif() if(MITK_LIBRARY_DIRS) list(APPEND _dir_candidates ${MITK_LIBRARY_DIRS}) endif() ################################################################### #get the search paths added by the mitkFunctionAddLibrarySearchPath file(GLOB _additional_path_info_files "${MITK_SUPERBUILD_BINARY_DIR}/MITK-AdditionalLibPaths/*.cmake") foreach(_additional_path_info_file ${_additional_path_info_files}) get_filename_component(_additional_info_name ${_additional_path_info_file} NAME_WE) include(${_additional_path_info_file}) if(GLS_DEBUG) list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_DEBUG_LIBRARY_SEARCH_PATHS}) elseif(GLS_MINSIZEREL) list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_MINSIZEREL_LIBRARY_SEARCH_PATHS}) elseif(GLS_RELWITHDEBINFO) list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_RELWITHDEBINFO_LIBRARY_SEARCH_PATHS}) else() #Release list(APPEND _dir_candidates ${${_additional_info_name}_ADDITIONAL_RELEASE_LIBRARY_SEARCH_PATHS}) endif() endforeach(_additional_path_info_file ${_additional_path_info_files}) ############################################### #sanitize all candidates and compile final list list(REMOVE_DUPLICATES _dir_candidates) set(_search_dirs ) foreach(_dir ${_dir_candidates}) if(EXISTS "${_dir}/${intermediate_dir}") list(APPEND _search_dirs "${_dir}/${intermediate_dir}") else() list(APPEND _search_dirs "${_dir}") endif() endforeach() # Special handling for "internal" search dirs. The intermediate directory # might not have been created yet, so we can't check for its existence. # Hence we just add it for Windows without checking. set(_internal_search_dirs "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins") if(WIN32) foreach(_dir ${_internal_search_dirs}) set(_search_dirs "${_dir}/${intermediate_dir}" ${_search_dirs}) endforeach() else() set(_search_dirs ${_internal_search_dirs} ${_search_dirs}) endif() list(REMOVE_DUPLICATES _search_dirs) set(${search_path} ${_search_dirs} PARENT_SCOPE) endfunction() diff --git a/CMakeExternals/ExternalProjectList.cmake b/CMakeExternals/ExternalProjectList.cmake index e9cd818848..ab452fc867 100644 --- a/CMakeExternals/ExternalProjectList.cmake +++ b/CMakeExternals/ExternalProjectList.cmake @@ -1,26 +1,26 @@ mitkFunctionAddExternalProject(NAME Poco ON COMPONENTS Foundation Net Util XML Zip) mitkFunctionAddExternalProject(NAME DCMTK ON DOC "EXPERIMENTAL, superbuild only: Use DCMTK in MITK") mitkFunctionAddExternalProject(NAME OpenIGTLink OFF) mitkFunctionAddExternalProject(NAME tinyxml ON ADVANCED) mitkFunctionAddExternalProject(NAME GDCM ON ADVANCED) mitkFunctionAddExternalProject(NAME Eigen ON ADVANCED DOC "Use the Eigen library") mitkFunctionAddExternalProject(NAME ANN ON ADVANCED DOC "Use Approximate Nearest Neighbor Library") mitkFunctionAddExternalProject(NAME CppUnit ON ADVANCED DOC "Use CppUnit for unit tests") mitkFunctionAddExternalProject(NAME PCRE OFF ADVANCED NO_PACKAGE) mitkFunctionAddExternalProject(NAME HDF5 ON ADVANCED) mitkFunctionAddExternalProject(NAME SWIG OFF ADVANCED NO_PACKAGE DEPENDS PCRE) mitkFunctionAddExternalProject(NAME OpenCV OFF) mitkFunctionAddExternalProject(NAME Vigra OFF DEPENDS HDF5) mitkFunctionAddExternalProject(NAME ITK ON NO_CACHE DEPENDS HDF5) mitkFunctionAddExternalProject(NAME VTK ON NO_CACHE) mitkFunctionAddExternalProject(NAME Boost ON NO_CACHE) mitkFunctionAddExternalProject(NAME ZLIB OFF ADVANCED) mitkFunctionAddExternalProject(NAME cpprestsdk OFF DEPENDS Boost ZLIB ADVANCED) -mitkFunctionAddExternalProject(NAME ACVD OFF DOC "Use Approximated Centroidal Voronoi Diagrams") +mitkFunctionAddExternalProject(NAME OpenMesh OFF) mitkFunctionAddExternalProject(NAME CTK ON DEPENDS Qt5 DCMTK DOC "Use CTK in MITK") mitkFunctionAddExternalProject(NAME DCMQI ON DEPENDS DCMTK ITK DOC "Use dcmqi in MITK") mitkFunctionAddExternalProject(NAME MatchPoint OFF ADVANCED DEPENDS ITK DOC "Use the MatchPoint translation image registration library") if(MITK_USE_Qt5) mitkFunctionAddExternalProject(NAME Qwt ON ADVANCED DEPENDS Qt5) endif() diff --git a/CMakeExternals/ACVD.cmake b/CMakeExternals/OpenMesh.cmake similarity index 62% rename from CMakeExternals/ACVD.cmake rename to CMakeExternals/OpenMesh.cmake index f011a241ea..4e02342298 100644 --- a/CMakeExternals/ACVD.cmake +++ b/CMakeExternals/OpenMesh.cmake @@ -1,49 +1,50 @@ #----------------------------------------------------------------------------- -# ACVD +# OpenMesh #----------------------------------------------------------------------------- -if(MITK_USE_ACVD) +if(MITK_USE_OpenMesh) # Sanity checks - if(DEFINED ACVD_DIR AND NOT EXISTS ${ACVD_DIR}) - message(FATAL_ERROR "ACVD_DIR variable is defined but corresponds to non-existing directory") + if(DEFINED OpenMesh_DIR AND NOT EXISTS "${OpenMesh_DIR}") + message(FATAL_ERROR "OpenMesh_DIR variable is defined but corresponds to non-existing directory") endif() - set(proj ACVD) - set(proj_DEPENDENCIES VTK) - set(ACVD_DEPENDS ${proj}) + set(proj OpenMesh) + set(proj_DEPENDENCIES ) + set(OpenMesh_DEPENDS ${proj}) - if(NOT DEFINED ACVD_DIR) + if(NOT DEFINED OpenMesh_DIR) set(additional_args ) + if(CTEST_USE_LAUNCHERS) list(APPEND additional_args "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake" ) endif() ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} - URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/ACVD-vtk6_3d5ae388-patched.tar.gz - URL_MD5 a59e658c8309f6a7004705d86d520d12 + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/OpenMesh-8.1.tar.gz + URL_MD5 9e1eb6feeca3882ab95f9fc97681a4da CMAKE_GENERATOR ${gen} CMAKE_GENERATOR_PLATFORM ${gen_platform} CMAKE_ARGS ${ep_common_args} ${additional_args} - -DUSE_MULTITHREADING:BOOL=ON - -DBUILD_EXAMPLES:BOOL=OFF - -DVTK_DIR:PATH=${VTK_DIR} CMAKE_CACHE_ARGS ${ep_common_cache_args} + -DBUILD_APPS:BOOL=OFF + -DOPENMESH_BUILD_SHARED:BOOL=ON + -DOPENMESH_DOCS:BOOL=OFF CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} DEPENDS ${proj_DEPENDENCIES} ) - set(ACVD_DIR ${ep_prefix}) + set(OpenMesh_DIR "${ep_prefix}") mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() endif() diff --git a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox index c7b64520ce..9d0ec93913 100644 --- a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox +++ b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox @@ -1,216 +1,214 @@ /** \page BuildInstructionsPage Build Instructions \tableofcontents \section BuildInstructions_Introduction Introduction The CMake-based build system of MITK supports a "superbuild" process, meaning that it will download, configure, and build all required third-party libraries (except Qt) automatically. These instructions will show you how to use the MITK superbuild. \note This page explains explicitly how to build MITK itself. If you want to create your own project based on MITK, the process described below is completely automated. Please see \ref HowToNewProject. For more advanced users, the last sections explains how to inject custom build libraries into the superbuild process. \section BuildInstructions_Prerequisites Prerequisites You need: -# Git (there are also numerous third-party graphical clients available). We recommend using Git, but see below for a way how to get the current source code without using it. -# CMake (version \minimumCMakeVersion or higher) -# Qt 5.12 if you plan to develop Qt-based applications -# If you are using macOS you need an XCode installation and the Command Line Tools as it provides the neccessary compilers and SDKs \section BuildInstructions_Qt A note about Qt As we do not provide Qt in the MITK superbuild you need to install Qt manually. The Qt Company provides online installers for all supported platforms. \section BuildInstructions_Get_Source Get a source tree Since MITK is under active development we recommend to use Git to check out the latest stable release from the homepage. If you decide to use the most current nightly release, make sure to get a stable tree: Check the MITK dashboard before checking out. If the build tree is not clean, you can specify an older revision for the checkout or get a stable tar ball from www.mitk.org. To clone MITK's current Git repository do: \code git clone https://phabricator.mitk.org/source/mitk.git MITK \endcode \section BuildInstructions_Build_With_CMake Build MITK with CMake Create a new directory for the superbuild binary tree, change to it and call CMake: In the shell (assuming your current directory is the same as the one where you issued the git clone command): \code mkdir MITK-superbuild cd MITK-superbuild ccmake ../MITK \endcode If you use Windows or prefer to use the CMake GUI, start the CMake GUI and enter the location of the source tree and binary tree, choose a suitable generator and configure the project. CMake will present you a couple of options, these are the most important ones: - - CMAKE_PREFIX_PATH The path to your Qt installation, e.g., C:/Qt/5.12.6/msvc2017_64 or /home/user/Qt/5.12.6/gcc_64 - - MITK_USE_ACVD Build MITK code which depends on ACVD (this - will download and build ACVD) + - CMAKE_PREFIX_PATH The path to your Qt installation, e.g., C:/Qt/5.12.9/msvc2017_64 or /home/user/Qt/5.12.9/gcc_64 - MITK_USE_BLUEBERRY Build the BlueBerry application framework - MITK_USE_Boost_LIBRARIES If you need binary Boost libraries, specify them here. - MITK_USE_OpenCV Build MITK code which depends on OpenCV (this will download and build OpenCV 2.4) - MITK_USE_Python3 Enables Python wrapping in MITK. This will also configure ITK, VTK, and OpenCV (if enabled) to build Python wrappers. - MITK_USE_Qt5 Build MITK code which depends on Qt 5 If you are satisfied with the configuration of your MITK superbuild, generate the project files with CMake by pressing "Generate". Linux and macOS users usually just enter "make" (optionally supplying the number threads to be used for a parallel build): \code make -j6 \endcode Windows users using Visual Studio can open the generated MITK-superbuild.sln solution file in the MITK-superbuild directory and start the build by building the BUILD_ALL project. \section BuildInstructions_Customize Customize your MITK superbuild The MITK superbuild configures MITK as well as all external libraries. The build directories of these libraries, and of MITK itself are located inside the MITK-superbuild directory. For example, the directory layout may look like: \code MITK-superbuild |- ep "external projects" |-bin |-lib |-include |-src |- MITK-build \endcode To change the configuration of the MITK build itself, choose the MITK-build directory as the binary directory in the CMake GUI (not the MITK-superbuild directory). After generating the project files, build the MITK project by either issuing "make" in the MITK-build directory (Linux, macOS), or by opening MITK-build/MITK.sln (Windows). You may also change the configuration of any project configured via the superbuild process. Make sure to also build the changed project and also the projects which depend on it. \section BuildInstructions_Running Running Applications On Linux, just execute the application you want to run. MITK executables are located in MITK-superbuild/MITK-build/bin On Windows, the PATH environment variable must contain the directories containing the third-party libraries. This is automatically done from Visual Studio. For running the applications directly use the generated batch files in the MITK-superbuild/MITK-build/bin. \section BuildInstructions_Documentation Documentation If you have the Doxygen documentation tool installed, you get a new project (Visual Studio) or "make" target named "doc". You can build this to generate the HTML documentation of MITK in the Documentation/Doxygen directory of your MITK-build binary tree or in the MITK_DOXYGEN_OUTPUT_DIR CMake variable (if specified). \section BuildInstructions_Extending Extend MITK on your own (using the application framework BlueBerry) Please see \ref NewPluginPage \section BuildInstructions_As_Toolkit Use MITK in your own project (as a toolkit) To use MITK in your external project, add the CMake command find_package(MITK REQUIRED) to your CMakeLists.txt and make use of the CMake macros mitk_create_module() and mitk_create_executable() provided by MITK. Here is a very basic example CMakeLists.txt including MITK as a project: \code cmake_minimum_required(VERSION 3.10 FATAL_ERROR) project(MyProject) find_package(MITK 2018.04.02 REQUIRED) add_executable(MyApp main.cpp) target_link_libraries(MyApp MitkCore) \endcode with the main.ccp being \code #include #include int main() { MITK_INFO << "Hello world!"; return 0; } \endcode \section BuildInstructions_Advanced_Customization Superbuild customization You can inject pre-build third-party libraries into the MITK superbuild by setting certain CMake variables before the first configure step. MITK will then use these third-party libraries instead of downloading and building them by itself. Note that you must take care of configuring those libraries with all options MITK requires. The variables listed below are provided for injecting third-party libraries. Their occurrence in the CMake GUI or in ccmake may depend on specific MITK_USE_* options set to ON. You may also use the variable names below without the EXTERNAL_ prefix, for example when providing their values on a command line call to CMake. - EXTERNAL_BOOST_ROOT Set this variable to your custom Boost installation - EXTERNAL_CTK_DIR Set this variable to your CTK binary tree (the directory containing the CTKConfig.cmake file) - EXTERNAL_CableSwig_DIR Set this variable to your CableSwig binary tree for Python wrapping (the directory containing the CableSwigConfig.cmake file) - EXTERNAL_DCMTK_DIR Set this variable to your DCMTK binary tree (the directory containing the DCMTKConfig.cmake file) - EXTERNAL_GDCM_DIR Set this variable to your GDCM binary tree (the directory containing the GDCMConfig.cmake file) - EXTERNAL_ITK_DIR Set this variable to your ITK binary tree (the directory containing the ITKConfig.cmake file) - EXTERNAL_OpenCV_DIR Set this variable to your OpenCV binary tree (the directory containing the OpenCVConfig.cmake file) - EXTERNAL_VTK_DIR Set this variable to your VTK binary tree (the directory containing the VTKConfig.cmake file) To set CMake options before the first configure step is invoked, supply them on the command line, i.e. \code ccmake -DITK_DIR:PATH=/opt/ITK-release ../MITK \endcode */ diff --git a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox index de49eef830..5babea66ab 100644 --- a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox +++ b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox @@ -1,107 +1,107 @@ /** \page thirdpartylibs Third-party libraries The following third-party libraries can be used with MITK by default and can, in part, be automatically downloaded during superbuild. -\par ACVD - -https://www.creatis.insa-lyon.fr/site7/en/acvd - \par ANN https://www.cs.umd.edu/~mount/ANN/ \par Boost https://www.boost.org/ \par C++ REST SDK https://github.com/Microsoft/cpprestsdk/ \par CppUnit https://sourceforge.net/projects/cppunit/ \par CTK https://commontk.org/ \par DCMTK https://dicom.offis.de/dcmtk \par Eigen http://eigen.tuxfamily.org/index.php?title=Main_Page \par GDCM https://gdcm.sourceforge.net/ \par HDF5 https://support.hdfgroup.org/HDF5/ \par ITK https://itk.org/ \par MatchPoint https://www.dkfz.de/en/sidt/projects/MatchPoint/info.html \par OpenCL https://www.khronos.org/opencl/ \par OpenCV https://opencv.org/ \par OpenIGTLink http://openigtlink.org/ +\par OpenMesh + +https://www.openmesh.org/ + \par PCRE https://www.pcre.org/ \par POCO https://pocoproject.org/ \par Python https://www.python.org/ \par Qt https://www.qt.io/ \par Qwt http://qwt.sourceforge.net/ \par SWIG http://www.swig.org/ \par tinyxml http://www.grinninglizard.com/tinyxml/ \par VIGRA https://ukoethe.github.io/vigra/ \par VTK https://vtk.org/ \par zlib https://zlib.net/ For copyright information on any of the above toolkits see the corresponding home page or the corresponding source folder. */ diff --git a/Examples/Plugins/org.mitk.example.gui.imaging/CMakeLists.txt b/Examples/Plugins/org.mitk.example.gui.imaging/CMakeLists.txt index 9c8b4036f3..4618724877 100644 --- a/Examples/Plugins/org.mitk.example.gui.imaging/CMakeLists.txt +++ b/Examples/Plugins/org.mitk.example.gui.imaging/CMakeLists.txt @@ -1,7 +1,8 @@ project(org_mitk_example_gui_imaging) mitk_create_plugin( EXPORT_DIRECTIVE EXAMPLES_EXPORT EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgetsExt MitkSegmentation + PACKAGE_DEPENDS VTK|IOImage ) diff --git a/Examples/Plugins/org.mitk.example.gui.imaging/src/internal/simpleexample/QmitkSimpleExampleView.cpp b/Examples/Plugins/org.mitk.example.gui.imaging/src/internal/simpleexample/QmitkSimpleExampleView.cpp index 28a8de8327..d4e166ce06 100644 --- a/Examples/Plugins/org.mitk.example.gui.imaging/src/internal/simpleexample/QmitkSimpleExampleView.cpp +++ b/Examples/Plugins/org.mitk.example.gui.imaging/src/internal/simpleexample/QmitkSimpleExampleView.cpp @@ -1,418 +1,418 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkSimpleExampleView.h" +#include +#include +#include +#include +#include +#include + #include "QmitkRenderWindow.h" #include "QmitkStepperAdapter.h" #include "QmitkFFmpegWriter.h" #include "mitkNodePredicateNot.h" #include "mitkNodePredicateProperty.h" #include "mitkProperties.h" #include #include #include #include #include -#include -#include -#include -#include -#include -#include - const std::string QmitkSimpleExampleView::VIEW_ID = "org.mitk.views.simpleexample"; QmitkSimpleExampleView::QmitkSimpleExampleView() : m_Controls(nullptr), m_NavigatorsInitialized(false), m_Parent(nullptr) { } QmitkSimpleExampleView::~QmitkSimpleExampleView() { } void QmitkSimpleExampleView::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { m_Parent = parent; // create GUI widgets m_Controls = new Ui::QmitkSimpleExampleViewControls; m_Controls->setupUi(parent); this->CreateConnections(); this->RenderWindowPartActivated(this->GetRenderWindowPart()); } } void QmitkSimpleExampleView::SetFocus() { m_Controls->renderWindowComboBox->setFocus(); } void QmitkSimpleExampleView::RenderWindowPartActivated(mitk::IRenderWindowPart *renderWindowPart) { if (renderWindowPart == nullptr) { m_Parent->setEnabled(false); return; } QHashIterator renderIter(renderWindowPart->GetQmitkRenderWindows()); while (renderIter.hasNext()) { renderIter.next(); m_Controls->renderWindowComboBox->addItem(renderIter.key()); } RenderWindowSelected(m_Controls->renderWindowComboBox->currentText()); m_TimeStepper.reset(new QmitkStepperAdapter(m_Controls->sliceNavigatorTime, renderWindowPart->GetTimeNavigationController()->GetTime(), "sliceNavigatorTimeFromSimpleExample")); m_MovieStepper.reset(new QmitkStepperAdapter(m_Controls->movieNavigatorTime, renderWindowPart->GetTimeNavigationController()->GetTime(), "movieNavigatorTimeFromSimpleExample")); m_Parent->setEnabled(true); } void QmitkSimpleExampleView::RenderWindowPartDeactivated(mitk::IRenderWindowPart * /*renderWindowPart*/) { m_Parent->setEnabled(false); m_SliceStepper.reset(); m_TimeStepper.reset(); m_MovieStepper.reset(); m_Controls->renderWindowComboBox->clear(); } void QmitkSimpleExampleView::CreateConnections() { if (m_Controls) { connect(m_Controls->renderWindowComboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(RenderWindowSelected(QString))); connect(m_Controls->stereoSelect, SIGNAL(activated(int)), this, SLOT(StereoSelectionChanged(int))); connect(m_Controls->reInitializeNavigatorsButton, SIGNAL(clicked()), this, SLOT(InitNavigators())); connect(m_Controls->genMovieButton, SIGNAL(clicked()), this, SLOT(GenerateMovie())); connect(m_Controls->m_TakeScreenshotBtn, SIGNAL(clicked()), this, SLOT(OnTakeScreenshot())); connect(m_Controls->m_TakeHighResScreenShotBtn, SIGNAL(clicked()), this, SLOT(OnTakeHighResolutionScreenshot())); } } void QmitkSimpleExampleView::InitNavigators() { /* get all nodes that have not set "includeInBoundingBox" to false */ mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New( mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); /* calculate bounding geometry of these nodes */ auto bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs); /* initialize the views to the bounding geometry */ m_NavigatorsInitialized = mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } /** * Returns path to the ffmpeg lib if configured in preferences. * * This implementation has been reused from MovieMaker view. * * @return The path to ffmpeg lib or empty string if not configured. */ QString QmitkSimpleExampleView::GetFFmpegPath() const { berry::IPreferences::Pointer preferences = berry::Platform::GetPreferencesService()->GetSystemPreferences()->Node("/org.mitk.gui.qt.ext.externalprograms"); return preferences.IsNotNull() ? preferences->Get("ffmpeg", "") : ""; } /** * Reads pixels from specified render window. * * This implementation has been reused from MovieMaker view. * * @param renderWindow * @param x * @param y * @param width * @param height * @return */ static unsigned char *ReadPixels(vtkRenderWindow *renderWindow, int x, int y, int width, int height) { if (renderWindow == nullptr) return nullptr; unsigned char *frame = new unsigned char[width * height * 3]; renderWindow->MakeCurrent(); glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, frame); return frame; } /** * Records a movie from the selected render window with a default frame rate of 30 Hz. * * Parts of this implementation have been reused from MovieMaker view. */ void QmitkSimpleExampleView::GenerateMovie() { QmitkRenderWindow *movieRenderWindow = GetSelectedRenderWindow(); mitk::Stepper::Pointer stepper = movieRenderWindow->GetSliceNavigationController()->GetSlice(); QmitkFFmpegWriter *movieWriter = new QmitkFFmpegWriter(m_Parent); const QString ffmpegPath = GetFFmpegPath(); if (ffmpegPath.isEmpty()) { QMessageBox::information( nullptr, "Movie Maker", "

Set path to FFmpeg1 in preferences (Window -> Preferences... " "(Ctrl+P) -> External Programs) to be able to record your movies to video files.

" "

If you are using Linux, chances are good that FFmpeg is included in the official package " "repositories.

" "

[1] Download FFmpeg from ffmpeg.org

"); return; } movieWriter->SetFFmpegPath(GetFFmpegPath()); - vtkRenderWindow *renderWindow = movieRenderWindow->GetRenderWindow(); + vtkRenderWindow *renderWindow = movieRenderWindow->renderWindow(); if (renderWindow == nullptr) return; const int border = 3; const int x = border; const int y = border; int width = renderWindow->GetSize()[0] - border * 2; int height = renderWindow->GetSize()[1] - border * 2; if (width & 1) --width; if (height & 1) --height; if (width < 16 || height < 16) return; movieWriter->SetSize(width, height); movieWriter->SetFramerate(30); QString saveFileName = QFileDialog::getSaveFileName(nullptr, "Specify a filename", "", "Movie (*.mp4)"); if (saveFileName.isEmpty()) return; if (!saveFileName.endsWith(".mp4")) saveFileName += ".mp4"; movieWriter->SetOutputPath(saveFileName); const unsigned int numberOfFrames = stepper->GetSteps() - stepper->GetPos(); try { movieWriter->Start(); for (unsigned int currentFrame = 0; currentFrame < numberOfFrames; ++currentFrame) { mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); renderWindow->MakeCurrent(); unsigned char *frame = ReadPixels(renderWindow, x, y, width, height); movieWriter->WriteFrame(frame); delete[] frame; stepper->Next(); } movieWriter->Stop(); mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); } catch (const mitk::Exception &exception) { mitk::RenderingManager::GetInstance()->ForceImmediateUpdateAll(); QMessageBox::critical(nullptr, "Generate Movie", exception.GetDescription()); } } void QmitkSimpleExampleView::StereoSelectionChanged(int id) { /* From vtkRenderWindow.h tells us about stereo rendering: Set/Get what type of stereo rendering to use. CrystalEyes mode uses frame-sequential capabilities available in OpenGL to drive LCD shutter glasses and stereo projectors. RedBlue mode is a simple type of stereo for use with red-blue glasses. Anaglyph mode is a superset of RedBlue mode, but the color output channels can be configured using the AnaglyphColorMask and the color of the original image can be (somewhat maintained using AnaglyphColorSaturation; the default colors for Anaglyph mode is red-cyan. Interlaced stereo mode produces a composite image where horizontal lines alternate between left and right views. StereoLeft and StereoRight modes choose one or the other stereo view. Dresden mode is yet another stereoscopic interleaving. */ mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart(); vtkRenderWindow *vtkrenderwindow = renderWindowPart->GetQmitkRenderWindow("3d")->GetVtkRenderWindow(); // note: foreground vtkRenderers (at least the department logo renderer) produce errors in stereoscopic visualization. // Therefore, we disable the logo visualization during stereo rendering. switch (id) { case 0: vtkrenderwindow->StereoRenderOff(); break; case 1: vtkrenderwindow->SetStereoTypeToRedBlue(); vtkrenderwindow->StereoRenderOn(); renderWindowPart->EnableDecorations(false, QStringList(mitk::IRenderWindowPart::DECORATION_LOGO)); break; case 2: vtkrenderwindow->SetStereoTypeToDresden(); vtkrenderwindow->StereoRenderOn(); renderWindowPart->EnableDecorations(false, QStringList(mitk::IRenderWindowPart::DECORATION_LOGO)); break; } mitk::BaseRenderer::GetInstance(vtkrenderwindow)->SetMapperID(mitk::BaseRenderer::Standard3D); renderWindowPart->RequestUpdate(); } QmitkRenderWindow *QmitkSimpleExampleView::GetSelectedRenderWindow() const { QString id = m_Controls->renderWindowComboBox->currentText(); if (id.isEmpty()) { return nullptr; } else { return this->GetRenderWindowPart()->GetQmitkRenderWindow(id); } } void QmitkSimpleExampleView::OnTakeHighResolutionScreenshot() { QString filter; QString fileName = QFileDialog::getSaveFileName( nullptr, "Save screenshot to...", QDir::currentPath(), m_PNGExtension + ";;" + m_JPGExtension, &filter); vtkRenderer *renderer = this->GetSelectedRenderWindow()->GetRenderer()->GetVtkRenderer(); if (renderer == nullptr) return; this->TakeScreenshot(renderer, 4, fileName, filter); } void QmitkSimpleExampleView::OnTakeScreenshot() { QString filter; QString fileName = QFileDialog::getSaveFileName( nullptr, "Save screenshot to...", QDir::currentPath(), m_PNGExtension + ";;" + m_JPGExtension, &filter); QmitkRenderWindow *renWin = this->GetSelectedRenderWindow(); if (renWin == nullptr) return; vtkRenderer *renderer = renWin->GetRenderer()->GetVtkRenderer(); if (renderer == nullptr) return; this->TakeScreenshot(renderer, 1, fileName, filter); } void QmitkSimpleExampleView::TakeScreenshot(vtkRenderer *renderer, unsigned int magnificationFactor, QString fileName, QString filter) { if ((renderer == nullptr) || (magnificationFactor < 1) || fileName.isEmpty()) return; bool doubleBuffering(renderer->GetRenderWindow()->GetDoubleBuffer()); renderer->GetRenderWindow()->DoubleBufferOff(); vtkImageWriter *fileWriter = nullptr; QFileInfo fi(fileName); QString suffix = fi.suffix().toLower(); if (suffix.isEmpty() || (suffix != "png" && suffix != "jpg" && suffix != "jpeg")) { if (filter == m_PNGExtension) { suffix = "png"; } else if (filter == m_JPGExtension) { suffix = "jpg"; } fileName += "." + suffix; } if (suffix.compare("jpg", Qt::CaseInsensitive) == 0 || suffix.compare("jpeg", Qt::CaseInsensitive) == 0) { vtkJPEGWriter *w = vtkJPEGWriter::New(); w->SetQuality(100); w->ProgressiveOff(); fileWriter = w; } else // default is png { fileWriter = vtkPNGWriter::New(); } vtkRenderLargeImage *magnifier = vtkRenderLargeImage::New(); magnifier->SetInput(renderer); magnifier->SetMagnification(magnificationFactor); fileWriter->SetInputConnection(magnifier->GetOutputPort()); fileWriter->SetFileName(fileName.toLatin1()); // vtkRenderLargeImage has problems with different layers, therefore we have to // temporarily deactivate all other layers. // we set the background to white, because it is nicer than black... double oldBackground[3]; renderer->GetBackground(oldBackground); double white[] = {1.0, 1.0, 1.0}; renderer->SetBackground(white); mitk::IRenderWindowPart *renderWindowPart = this->GetRenderWindowPart(); renderWindowPart->EnableDecorations(false); fileWriter->Write(); fileWriter->Delete(); renderWindowPart->EnableDecorations(true); renderer->SetBackground(oldBackground); renderer->GetRenderWindow()->SetDoubleBuffer(doubleBuffering); } void QmitkSimpleExampleView::RenderWindowSelected(const QString &id) { if (!id.isEmpty()) { m_SliceStepper.reset(new QmitkStepperAdapter( m_Controls->sliceNavigator, this->GetRenderWindowPart()->GetQmitkRenderWindow(id)->GetSliceNavigationController()->GetSlice(), "sliceNavigatorFromSimpleExample")); } } diff --git a/Modules/Classification/CLMiniApps/CMakeLists.txt b/Modules/Classification/CLMiniApps/CMakeLists.txt index 3755b73a83..6e45122c9a 100644 --- a/Modules/Classification/CLMiniApps/CMakeLists.txt +++ b/Modules/Classification/CLMiniApps/CMakeLists.txt @@ -1,117 +1,117 @@ option(BUILD_ClassificationMiniApps "Build commandline tools for classification" OFF) if(BUILD_ClassificationMiniApps OR MITK_BUILD_ALL_APPS) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) # list of miniapps # if an app requires additional dependencies # they are added after a "^^" and separated by "_" set( classificationminiapps RandomForestTraining^^MitkCLVigraRandomForest NativeHeadCTSegmentation^^MitkCLVigraRandomForest ManualSegmentationEvaluation^^MitkCLVigraRandomForest CLScreenshot^^MitkCore_MitkQtWidgetsExt_MitkCLUtilities CLDicom2Nrrd^^MitkCore CLResampleImageToReference^^MitkCore CLGlobalImageFeatures^^MitkCLUtilities_MitkQtWidgetsExt CLMRNormalization^^MitkCLUtilities_MitkCLMRUtilities CLStaple^^MitkCLUtilities CLVoxelFeatures^^MitkCLUtilities CLPolyToNrrd^^ CLPlanarFigureToNrrd^^MitkCore_MitkSegmentation_MitkMultilabel CLSimpleVoxelClassification^^MitkDataCollection_MitkCLVigraRandomForest CLVoxelClassification^^MitkDataCollection_MitkCLImportanceWeighting_MitkCLVigraRandomForest CLBrainMask^^MitkCLUtilities XRaxSimulationFromCT^^MitkCLUtilities CLRandomSampling^^MitkCore_MitkCLUtilities CLRemoveEmptyVoxels^^MitkCore CLN4^^MitkCore CLSkullMask^^MitkCore CLPointSetToSegmentation^^ CLMultiForestPrediction^^MitkDataCollection_MitkCLVigraRandomForest CLNrrdToPoly^^MitkCore CL2Dto3DImage^^MitkCore CLWeighting^^MitkCore_MitkCLImportanceWeighting_MitkCLUtilities CLOverlayRoiCenterOfMass^^MitkCore_MitkCLUtilities_MitkQtWidgetsExt CLLungSegmentation^^MitkCore_MitkSegmentation_MitkMultilabel ) foreach(classificationminiapps ${classificationminiapps}) # extract mini app name and dependencies string(REPLACE "^^" "\\;" miniapp_info ${classificationminiapps}) set(miniapp_info_list ${miniapp_info}) list(GET miniapp_info_list 0 appname) list(GET miniapp_info_list 1 raw_dependencies) string(REPLACE "_" "\\;" dependencies "${raw_dependencies}") set(dependencies_list ${dependencies}) mitk_create_executable(${appname} DEPENDS MitkCore MitkCLCore MitkCommandLine ${dependencies_list} - PACKAGE_DEPENDS ITK Qt5|Core Vigra + PACKAGE_DEPENDS ITK Qt5|Core Vigra VTK|IOImage CPP_FILES ${appname}.cpp ) if(EXECUTABLE_IS_ENABLED) # On Linux, create a shell script to start a relocatable application if(UNIX AND NOT APPLE) install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME ${EXECUTABLE_TARGET}.sh) endif() get_target_property(_is_bundle ${EXECUTABLE_TARGET} MACOSX_BUNDLE) if(APPLE) if(_is_bundle) set(_target_locations ${EXECUTABLE_TARGET}.app) set(${_target_locations}_qt_plugins_install_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS) set(_bundle_dest_dir ${EXECUTABLE_TARGET}.app/Contents/MacOS) set(_qt_plugins_for_current_bundle ${EXECUTABLE_TARGET}.app/Contents/MacOS) set(_qt_conf_install_dirs ${EXECUTABLE_TARGET}.app/Contents/Resources) install(TARGETS ${EXECUTABLE_TARGET} BUNDLE DESTINATION . ) else() if(NOT MACOSX_BUNDLE_NAMES) set(_qt_conf_install_dirs bin) set(_target_locations bin/${EXECUTABLE_TARGET}) set(${_target_locations}_qt_plugins_install_dir bin) install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin) else() foreach(bundle_name ${MACOSX_BUNDLE_NAMES}) list(APPEND _qt_conf_install_dirs ${bundle_name}.app/Contents/Resources) set(_current_target_location ${bundle_name}.app/Contents/MacOS/${EXECUTABLE_TARGET}) list(APPEND _target_locations ${_current_target_location}) set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS) message( " set(${_current_target_location}_qt_plugins_install_dir ${bundle_name}.app/Contents/MacOS) ") install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION ${bundle_name}.app/Contents/MacOS/) endforeach() endif() endif() else() set(_target_locations bin/${EXECUTABLE_TARGET}${CMAKE_EXECUTABLE_SUFFIX}) set(${_target_locations}_qt_plugins_install_dir bin) set(_qt_conf_install_dirs bin) install(TARGETS ${EXECUTABLE_TARGET} RUNTIME DESTINATION bin) endif() endif() endforeach() mitk_create_executable(CLMatchPointReg DEPENDS MitkCore MitkCLUtilities MitkMatchPointRegistration MitkCommandLine MitkMatchPointRegistrationUI PACKAGE_DEPENDS ITK Qt5|Core Vigra MatchPoint CPP_FILES CLMatchPointReg.cpp ) # On Linux, create a shell script to start a relocatable application if(UNIX AND NOT APPLE) install(PROGRAMS "${MITK_SOURCE_DIR}/CMake/RunInstalledApp.sh" DESTINATION "." RENAME ${EXECUTABLE_TARGET}.sh) endif() if(EXECUTABLE_IS_ENABLED) MITK_INSTALL_TARGETS(EXECUTABLES ${EXECUTABLE_TARGET}) endif() endif() diff --git a/Modules/Core/include/mitkPointSet.h b/Modules/Core/include/mitkPointSet.h index 99383bfea8..4a55101604 100755 --- a/Modules/Core/include/mitkPointSet.h +++ b/Modules/Core/include/mitkPointSet.h @@ -1,352 +1,348 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef MITKPointSet_H_HEADER_INCLUDED #define MITKPointSet_H_HEADER_INCLUDED #include "mitkBaseData.h" #include #include namespace mitk { /** - * \brief Data structure which stores a set of points. Superclass of - * mitk::Mesh. + * \brief Data structure which stores a set of points. * * 3D points are grouped within a point set; for time resolved usage, one point * set is created and maintained per time step. A point entry consists of the * point coordinates and point data. * * The point data includes a point ID (unique identifier to address this point * within the point set), the selection state of the point and the type of * the point. * * For further information about different point types see * mitk::PointSpecificationType in mitkVector.h. * * Inserting a point is accompanied by an event, containing an index. The new * point is inserted into the list at the specified position. At the same time * an internal ID is generated and stored for the point. Points at specific time * steps are accessed by specifying the time step number (which defaults to 0). * * The points of itk::PointSet stores the points in a pointContainer * (MapContainer). The points are best accessed by using a ConstIterator (as * defined in MapContainer); avoid access via index. * - * The class internally uses an itk::Mesh for each time step, because - * mitk::Mesh is derived from mitk::PointSet and needs the itk::Mesh structure - * which is also derived from itk::PointSet. Thus several typedefs which seem - * to be in wrong place, are declared here (for example SelectedLinesType). + * The class internally uses an itk::Mesh for each time step. * * \section mitkPointSetDisplayOptions * * The default mappers for this data structure are mitk::PointSetGLMapper2D and * mitk::PointSetVtkMapper3D. See these classes for display options which can * can be set via properties. * * \section Events * * PointSet issues the following events, for which observers can register * (the below events are grouped into a class hierarchy as indicated by * identation level; e.g. PointSetSizeChangeEvent comprises PointSetAddEvent * and PointSetRemoveEvent): * * * PointSetEvent subsumes all PointSet events * PointSetMoveEvent issued when a point of the PointSet is moved * PointSetSizeChangeEvent subsumes add and remove events * PointSetAddEvent issued when a point is added to the PointSet * PointSetRemoveEvent issued when a point is removed from the PointSet * * \ingroup PSIO * \ingroup Data */ class MITKCORE_EXPORT PointSet : public BaseData { public: mitkClassMacro(PointSet, BaseData); itkFactorylessNewMacro(Self); itkCloneMacro(Self); typedef mitk::ScalarType CoordinateType; typedef mitk::ScalarType InterpolationWeightType; static const unsigned int PointDimension = 3; static const unsigned int MaxTopologicalDimension = 3; /** * \brief struct for data of a point */ struct MITKCORE_EXPORT PointDataType { unsigned int id; // to give the point a special ID bool selected; // information about if the point is selected mitk::PointSpecificationType pointSpec; // specifies the type of the point bool operator==(const PointDataType &other) const; }; /** * \brief cellDataType, that stores all indexes of the lines, that are * selected e.g.: points A,B and C.Between A and B there is a line with * index 0. If vector of cellData contains 1 and 2, then the lines between * B and C and C and A is selected. */ typedef std::vector SelectedLinesType; typedef SelectedLinesType::iterator SelectedLinesIter; struct CellDataType { // used to set the whole cell on selected bool selected; // indexes of selected lines. 0 is between pointId 0 and 1 SelectedLinesType selectedLines; // is the polygon already finished and closed bool closed; }; typedef itk::DefaultDynamicMeshTraits MeshTraits; typedef itk::Mesh MeshType; typedef MeshType DataType; typedef Point3D PointType; typedef DataType::PointIdentifier PointIdentifier; typedef DataType::PointsContainer PointsContainer; typedef DataType::PointsContainerIterator PointsIterator; typedef DataType::PointsContainer::ConstIterator PointsConstIterator; typedef DataType::PointDataContainer PointDataContainer; typedef DataType::PointDataContainerIterator PointDataIterator; typedef DataType::PointDataContainerIterator PointDataConstIterator; void Expand(unsigned int timeSteps) override; /** \brief executes the given Operation */ void ExecuteOperation(Operation *operation) override; /** \brief returns the current size of the point-list */ virtual int GetSize(unsigned int t = 0) const; virtual unsigned int GetPointSetSeriesSize() const; /** \brief returns the pointset */ virtual DataType::Pointer GetPointSet(int t = 0) const; PointsIterator Begin(int t = 0); PointsConstIterator Begin(int t = 0) const; PointsIterator End(int t = 0); PointsConstIterator End(int t = 0) const; /** * \brief Get an iterator to the max ID element if existent. Return End() otherwise. */ PointsIterator GetMaxId(int t = 0); /** * \brief Get the point with ID id in world coordinates * * check if the ID exists. If it doesn't exist, then return 0,0,0 */ PointType GetPoint(PointIdentifier id, int t = 0) const; /** * \brief Get the point with ID id in world coordinates * * If a point exists for the ID id, the point is returned in the parameter point * and the method returns true. If the ID does not exist, the method returns false */ bool GetPointIfExists(PointIdentifier id, PointType *point, int t = 0) const; /** * \brief Set the given point in world coordinate system into the itkPointSet. */ void SetPoint(PointIdentifier id, PointType point, int t = 0); /** * \brief Set the given point in world coordinate system with the given PointSpecificationType */ void SetPoint(PointIdentifier id, PointType point, PointSpecificationType spec, int t = 0); /** * \brief Set the given point in world coordinate system into the itkPointSet. */ void InsertPoint(PointIdentifier id, PointType point, int t = 0); /** * \brief Set the given point in world coordinate system with given PointSpecificationType */ void InsertPoint(PointIdentifier id, PointType point, PointSpecificationType spec, int t); /** * \brief Insert the given point in world coordinate system with incremented max id at time step t. */ PointIdentifier InsertPoint(PointType point, int t = 0); /** * \brief Remove point with given id at timestep t, if existent */ bool RemovePointIfExists(PointIdentifier id, int t = 0); /** * \brief Remove max id point at timestep t and return iterator to precedent point */ PointsIterator RemovePointAtEnd(int t = 0); /** * \brief Swap a point at the given position (id) with the upper point (moveUpwards=true) or with the lower point * (moveUpwards=false). * If upper or lower index does not exist false is returned, if swap was successful true. */ bool SwapPointPosition(PointIdentifier id, bool moveUpwards, int t = 0); /** * \brief searches a selected point and returns the id of that point. * If no point is found, then -1 is returned */ virtual int SearchSelectedPoint(int t = 0) const; /** \brief returns true if a point exists at this position */ virtual bool IndexExists(int position, int t = 0) const; /** \brief to get the state selected/unselected of the point on the * position */ virtual bool GetSelectInfo(int position, int t = 0) const; virtual void SetSelectInfo(int position, bool selected, int t = 0); /** \brief to get the type of the point at the position and the moment */ virtual PointSpecificationType GetSpecificationTypeInfo(int position, int t) const; /** \brief returns the number of selected points */ virtual int GetNumberOfSelected(int t = 0) const; /** * \brief searches a point in the list == point +/- distance * * \param point is in world coordinates. * \param distance is in mm. * \param t * returns -1 if no point is found * or the position in the list of the first match */ int SearchPoint(Point3D point, ScalarType distance, int t = 0) const; bool IsEmptyTimeStep(unsigned int t) const override; // virtual methods, that need to be implemented void UpdateOutputInformation() override; void SetRequestedRegionToLargestPossibleRegion() override; bool RequestedRegionIsOutsideOfTheBufferedRegion() override; bool VerifyRequestedRegion() override; void SetRequestedRegion(const itk::DataObject *data) override; // Method for subclasses virtual void OnPointSetChange(){}; protected: mitkCloneMacro(Self); PointSet(); PointSet(const PointSet &other); ~PointSet() override; void PrintSelf(std::ostream &os, itk::Indent indent) const override; ///< print content of the object to os void ClearData() override; void InitializeEmpty() override; /** \brief swaps point coordinates and point data of the points with identifiers id1 and id2 */ bool SwapPointContents(PointIdentifier id1, PointIdentifier id2, int t = 0); typedef std::vector PointSetSeries; PointSetSeries m_PointSetSeries; DataType::PointsContainer::Pointer m_EmptyPointsContainer; /** * @brief flag to indicate the right time to call SetBounds **/ bool m_CalculateBoundingBox; }; /** * @brief Equal A function comparing two pointsets for beeing identical. * @warning This method is deprecated and will not be available in the future. Use the \a bool mitk::Equal(const * mitk::PointSet& p1, const mitk::PointSet& p2) instead. * * @ingroup MITKTestingAPI * * The function compares the Geometry, the size and all points element-wise. * The parameter eps is a tolarence value for all methods which are internally used for comparion. * * @param rightHandSide Compare this against leftHandSide. * @param leftHandSide Compare this against rightHandSide. * @param eps Tolarence for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @param checkGeometry if comparing point sets loaded from a file, the geometries might be different and must not be * compared. In all other cases, you should compare the geometries. * @return True, if all subsequent comparisons are true, false otherwise */ DEPRECATED(MITKCORE_EXPORT bool Equal(const mitk::PointSet *leftHandSide, const mitk::PointSet *rightHandSide, mitk::ScalarType eps, bool verbose, bool checkGeometry = true)); /** * @brief Equal A function comparing two pointsets for beeing identical. * * @ingroup MITKTestingAPI * * The function compares the Geometry, the size and all points element-wise. * The parameter eps is a tolarence value for all methods which are internally used for comparion. * * @param rightHandSide Compare this against leftHandSide. * @param leftHandSide Compare this against rightHandSide. * @param eps Tolarence for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @param checkGeometry if comparing point sets loaded from a file, the geometries might be different and must not be * compared. In all other cases, you should compare the geometries. * @return True, if all subsequent comparisons are true, false otherwise */ MITKCORE_EXPORT bool Equal(const mitk::PointSet &leftHandSide, const mitk::PointSet &rightHandSide, mitk::ScalarType eps, bool verbose, bool checkGeometry = true); itkEventMacro(PointSetEvent, itk::AnyEvent); itkEventMacro(PointSetMoveEvent, PointSetEvent); itkEventMacro(PointSetSizeChangeEvent, PointSetEvent); itkEventMacro(PointSetAddEvent, PointSetSizeChangeEvent); itkEventMacro(PointSetRemoveEvent, PointSetSizeChangeEvent); itkEventMacro(PointSetExtendTimeRangeEvent, PointSetEvent); } // namespace mitk #endif /* MITKPointSet_H_HEADER_INCLUDED */ diff --git a/Modules/Core/src/IO/mitkSurfaceStlIO.cpp b/Modules/Core/src/IO/mitkSurfaceStlIO.cpp index e64e9a1634..21aeb441e0 100644 --- a/Modules/Core/src/IO/mitkSurfaceStlIO.cpp +++ b/Modules/Core/src/IO/mitkSurfaceStlIO.cpp @@ -1,160 +1,160 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkSurfaceStlIO.h" #include "mitkIOMimeTypes.h" #include "mitkLocaleSwitch.h" #include "mitkSurface.h" #include #include #include #include #include #include #include namespace mitk { - std::string SurfaceStlIO::OPTION_MERGE_POINTS() - { - static std::string s = "Merge points"; - return s; - } + // std::string SurfaceStlIO::OPTION_MERGE_POINTS() + // { + // static std::string s = "Merge points"; + // return s; + // } std::string SurfaceStlIO::OPTION_TAG_SOLIDS() { static std::string s = "Tag solids"; return s; } std::string SurfaceStlIO::OPTION_CLEAN() { static std::string s = "Clean poly data"; return s; } SurfaceStlIO::SurfaceStlIO() : SurfaceVtkIO(Surface::GetStaticNameOfClass(), IOMimeTypes::STEREOLITHOGRAPHY_MIMETYPE(), "Stereolithography") { Options defaultOptions; - defaultOptions[OPTION_MERGE_POINTS()] = us::Any(true); + // defaultOptions[OPTION_MERGE_POINTS()] = us::Any(true); defaultOptions[OPTION_TAG_SOLIDS()] = us::Any(false); defaultOptions[OPTION_CLEAN()] = us::Any(true); this->SetDefaultReaderOptions(defaultOptions); this->RegisterService(); } std::vector> SurfaceStlIO::DoRead() { LocaleSwitch localeSwitch("C"); Options options = this->GetReaderOptions(); mitk::Surface::Pointer output = mitk::Surface::New(); vtkSmartPointer stlReader = vtkSmartPointer::New(); stlReader->SetFileName(this->GetLocalFileName().c_str()); - bool mergePoints = true; + // bool mergePoints = true; bool tagSolids = false; bool cleanData = true; try { - mergePoints = us::any_cast(options[OPTION_MERGE_POINTS()]); + // mergePoints = us::any_cast(options[OPTION_MERGE_POINTS()]); tagSolids = us::any_cast(options[OPTION_TAG_SOLIDS()]); cleanData = us::any_cast(options[OPTION_CLEAN()]); } catch (const us::BadAnyCastException &e) { MITK_WARN << "Unexpected error: " << e.what(); } - stlReader->SetMerging(mergePoints); + // stlReader->SetMerging(mergePoints); stlReader->SetScalarTags(tagSolids); vtkSmartPointer normalsGenerator = vtkSmartPointer::New(); normalsGenerator->SetInputConnection(stlReader->GetOutputPort()); vtkSmartPointer algo = normalsGenerator; if (cleanData) { vtkSmartPointer cleanPolyDataFilter = vtkSmartPointer::New(); cleanPolyDataFilter->SetInputConnection(normalsGenerator->GetOutputPort()); cleanPolyDataFilter->PieceInvariantOff(); cleanPolyDataFilter->ConvertLinesToPointsOff(); cleanPolyDataFilter->ConvertPolysToLinesOff(); cleanPolyDataFilter->ConvertStripsToPolysOff(); - if (mergePoints) - { + // if (mergePoints) + // { cleanPolyDataFilter->PointMergingOn(); - } + // } algo = cleanPolyDataFilter; } algo->Update(); if (algo->GetOutput() != nullptr) { vtkSmartPointer surfaceWithNormals = algo->GetOutput(); output->SetVtkPolyData(surfaceWithNormals); } std::vector result; result.push_back(output.GetPointer()); return result; } void SurfaceStlIO::Write() { LocaleSwitch localeSwitch("C"); ValidateOutputLocation(); const auto *input = dynamic_cast(this->GetInput()); const unsigned int timesteps = input->GetTimeGeometry()->CountTimeSteps(); for (unsigned int t = 0; t < timesteps; ++t) { std::string fileName; vtkSmartPointer polyData = this->GetPolyData(t, fileName); vtkSmartPointer triangleFilter = vtkSmartPointer::New(); triangleFilter->SetInputData(polyData); vtkSmartPointer writer = vtkSmartPointer::New(); writer->SetInputConnection(triangleFilter->GetOutputPort()); // The vtk stl writer cannot write to streams LocalFile localFile(this); writer->SetFileName(localFile.GetFileName().c_str()); if (writer->Write() == 0 || writer->GetErrorCode() != 0) { mitkThrow() << "Error during surface writing" << (writer->GetErrorCode() ? std::string(": ") + vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()) : std::string()); } if (this->GetOutputStream() && input->GetTimeGeometry()->CountTimeSteps() > 1) { MITK_WARN << "Writing multiple time-steps to output streams is not supported. " << "Only the first time-step will be written"; break; } } } SurfaceStlIO *SurfaceStlIO::IOClone() const { return new SurfaceStlIO(*this); } } diff --git a/Modules/Core/src/IO/mitkSurfaceStlIO.h b/Modules/Core/src/IO/mitkSurfaceStlIO.h index ffe36e1e60..2e95e8ab2e 100644 --- a/Modules/Core/src/IO/mitkSurfaceStlIO.h +++ b/Modules/Core/src/IO/mitkSurfaceStlIO.h @@ -1,45 +1,47 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef _MITK_SURFACE_STL_IO_H_ #define _MITK_SURFACE_STL_IO_H_ #include "mitkSurfaceVtkIO.h" namespace mitk { class SurfaceStlIO : public mitk::SurfaceVtkIO { public: SurfaceStlIO(); // -------------- AbstractFileReader ------------- using AbstractFileReader::Read; // -------------- AbstractFileWriter ------------- void Write() override; protected: std::vector> DoRead() override; private: SurfaceStlIO *IOClone() const override; - static std::string OPTION_MERGE_POINTS(); + // vtkSTLReader crashes with this option + // static std::string OPTION_MERGE_POINTS(); + static std::string OPTION_TAG_SOLIDS(); static std::string OPTION_CLEAN(); }; } #endif //_MITK_SURFACE_STL_IO_H_ diff --git a/Modules/DataTypesExt/files.cmake b/Modules/DataTypesExt/files.cmake index f8569f2e63..0508c5b9f1 100644 --- a/Modules/DataTypesExt/files.cmake +++ b/Modules/DataTypesExt/files.cmake @@ -1,46 +1,45 @@ file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") set(CPP_FILES mitkAffineBaseDataInteractor3D.cpp mitkAffineImageCropperInteractor.cpp mitkApplyDiffImageOperation.cpp mitkBoundingObject.cpp mitkBoundingObjectGroup.cpp mitkCellOperation.cpp mitkClippingPlaneInteractor3D.cpp mitkColorSequence.cpp mitkColorSequenceCycleH.cpp mitkColorSequenceRainbow.cpp mitkCompressedImageContainer.cpp mitkCone.cpp mitkCuboid.cpp mitkCylinder.cpp mitkDataStorageSelection.cpp mitkEllipsoid.cpp mitkGridRepresentationProperty.cpp mitkGridVolumeMapperProperty.cpp mitkLabeledImageLookupTable.cpp mitkLabeledImageVolumeCalculator.cpp mitkLineOperation.cpp mitkLookupTableSource.cpp - mitkMesh.cpp mitkMultiStepper.cpp mitkPlane.cpp mitkSurfaceDeformationDataInteractor3D.cpp mitkUnstructuredGrid.cpp mitkUnstructuredGridSource.cpp mitkVideoSource.cpp mitkColorConversions.cpp ) set(RESOURCE_FILES Interactions/AffineInteraction3D.xml Interactions/AffineMouseConfig.xml Interactions/AffineKeyConfig.xml Interactions/ClippingPlaneInteraction3D.xml Interactions/ClippingPlaneTranslationConfig.xml Interactions/ClippingPlaneRotationConfig.xml Interactions/ClippingPlaneDeformationConfig.xml Interactions/CropperDeformationConfig.xml ) diff --git a/Modules/DataTypesExt/include/mitkMesh.h b/Modules/DataTypesExt/include/mitkMesh.h deleted file mode 100644 index 215e71e648..0000000000 --- a/Modules/DataTypesExt/include/mitkMesh.h +++ /dev/null @@ -1,126 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#ifndef MITKMESH_H_HEADER_INCLUDED -#define MITKMESH_H_HEADER_INCLUDED - -#include "MitkDataTypesExtExports.h" -#include "mitkPointSet.h" - -#include -#include -#include -#include -#include - -#include -#include - -namespace mitk -{ - /** - * \brief DataStructure which stores a set of points (incl. pointdata) where - * each point can be associated to an element of a cell. - * - * A mesh contains several cells that can be of different celltypes - * (Line, Triangle, Polygone...). A cell is always closed. If a linestrip is - * to be created, then declare several cells, each containing one line. - * - * The operations take care of the coherence. If a line is added to an - * existing LineCell, then a TriangleCell is built with the old and the new - * parameter (and so on). Deletion is done the opposite way. - * - * Example for inserting a line into a TriangleCell: - * existing PIds ind the cell: 1, 2, 4; - * inserting (2, 3) so that new PIds in Cell: 1, 2, 3, 4 - * - * The cell is now of type QuadrilateralCell - * - * \ingroup Data - */ - class MITKDATATYPESEXT_EXPORT Mesh : public PointSet - { - public: - mitkClassMacro(Mesh, PointSet); - - itkFactorylessNewMacro(Self); - - itkCloneMacro(Self); - - typedef Superclass::DataType::CellType CellType; - typedef CellType::CellAutoPointer CellAutoPointer; - typedef Superclass::MeshTraits::CellTraits CellTraits; - typedef CellTraits::PointIdConstIterator PointIdConstIterator; - typedef CellTraits::PointIdIterator PointIdIterator; - typedef DataType::CellDataContainer CellDataContainer; - typedef DataType::CellDataContainerIterator CellDataIterator; - typedef Superclass::DataType::CellsContainer::Iterator CellIterator; - typedef Superclass::DataType::CellsContainer::ConstIterator ConstCellIterator; - typedef itk::PolygonCell PolygonType; - typedef MeshType::CellType::MultiVisitor MeshMultiVisitor; - - /** \brief returns the current number of cells in the mesh */ - virtual unsigned long GetNumberOfCells(int t = 0); - - /** \brief returns the mesh */ - virtual const DataType *GetMesh(int t = 0) const; - - /** \brief returns the mesh */ - virtual DataType *GetMesh(int t = 0); - - void SetMesh(DataType *mesh, int t = 0); - - /** \brief checks if the given point is in a cell and returns that cellId. - * Basicaly it searches lines and points that are hit. - */ - virtual bool EvaluatePosition(Point3D point, unsigned long &cellId, float precision, int t = 0); - - /** \brief searches for the next new cellId and returns that id */ - unsigned long GetNewCellId(int t = 0); - - /** \brief returns the first cell that includes the given pointId */ - virtual int SearchFirstCell(unsigned long pointId, int t = 0); - - /** \brief searches for a line, that is hit by the given point. - * Then returns the lineId and the cellId - */ - virtual bool SearchLine(Point3D point, float distance, unsigned long &lineId, unsigned long &cellId, int t = 0); - - /** \brief searches a line according to the cellId and lineId and returns - * the PointIds, that assign the line; if successful, then return - * param = true; - */ - virtual bool GetPointIds(unsigned long cellId, unsigned long lineId, int &idA, int &idB, int t = 0); - - /** \brief searches a selected cell and returns the id of that cell. If no - * cell is found, then -1 is returned - */ - virtual int SearchSelectedCell(int t = 0); - - /** \brief creates a BoundingBox and computes it with the given points of - * the cell. - * - * Returns the BoundingBox != IsNull() if successful. - */ - virtual DataType::BoundingBoxPointer GetBoundingBoxFromCell(unsigned long cellId, int t = 0); - - /** \brief executes the given Operation */ - void ExecuteOperation(Operation *operation) override; - - protected: - Mesh(); - ~Mesh() override; - }; - -} // namespace mitk - -#endif /* MITKMESH_H_HEADER_INCLUDED */ diff --git a/Modules/DataTypesExt/include/mitkMeshUtil.h b/Modules/DataTypesExt/include/mitkMeshUtil.h deleted file mode 100644 index a40c69cb20..0000000000 --- a/Modules/DataTypesExt/include/mitkMeshUtil.h +++ /dev/null @@ -1,1677 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#ifndef MITKMESHUTIL_H_INCLUDED -#define MITKMESHUTIL_H_INCLUDED - -#if (_MSC_VER == 1200) -#error MeshUtils currently not supported for MS Visual C++ 6.0. Sorry. -#endif - -//#include -#include -#include -#include -#include -#include -//#include -#include -//#include -//#include -//#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -template -class NullScalarAccessor -{ -public: - static inline double GetPointScalar(typename MeshType::PointDataContainer * /*pointData*/, - typename MeshType::PointIdentifier /*idx*/, - MeshType * /*mesh*/ = nullptr, - unsigned int /*type*/ = 0) - { - return (double)0.0; - }; - - static inline double GetCellScalar(typename MeshType::CellDataContainer * /*cellData*/, - typename MeshType::CellIdentifier /*idx*/, - MeshType * /*mesh*/ = nullptr, - unsigned int /*type*/ = 0) - { - return (double)0.0; - }; -}; - -template -class MeshScalarAccessor -{ -public: - static inline double GetPointScalar(typename MeshType::PointDataContainer *pointData, - typename MeshType::PointIdentifier idx, - MeshType * /*mesh*/ = nullptr, - unsigned int /*type*/ = 0) - { - return (double)pointData->GetElement(idx); - }; - - static inline double GetCellScalar(typename MeshType::CellDataContainer *cellData, - typename MeshType::CellIdentifier idx, - MeshType * /*mesh*/ = nullptr, - unsigned int /*type*/ = 0) - { - return (double)cellData->GetElement(idx); - }; -}; - -template -class MeanCurvatureAccessor : public NullScalarAccessor -{ -public: - static inline double GetPointScalar(typename MeshType::PointDataContainer * /*point*/, - typename MeshType::PointIdentifier idx, - MeshType *mesh, - unsigned int /*type*/ = 0) - { - typename MeshType::PixelType dis = 0; - mesh->GetPointData(idx, &dis); - return (double)dis; - }; -}; - -template -class SimplexMeshAccessor : public NullScalarAccessor -{ -public: - static inline double GetPointScalar(typename MeshType::PointDataContainer * /*point*/, - typename MeshType::PointIdentifier idx, - MeshType *mesh, - unsigned int type = 0) - { - typename MeshType::GeometryMapPointer geometryData = mesh->GetGeometryData(); - - if (type == 0) - { - double val = mesh->GetMeanCurvature(idx); - mesh->SetPointData(idx, val); - return val; - } - else if (type == 1) - { - double val = geometryData->GetElement(idx)->meanTension; - mesh->SetPointData(idx, val); - return val; - } - else if (type == 2) - { - double val = geometryData->GetElement(idx)->externalForce.GetNorm(); - mesh->SetPointData(idx, val); - return val; - } - else if (type == 3) - return geometryData->GetElement(idx)->internalForce.GetNorm(); - else if (type == 4) - return geometryData->GetElement(idx)->externalForce.GetNorm() * mesh->GetDistance(idx); - else if (type == 5) - { - typename MeshType::PixelType dis = 0; - mesh->GetPointData(idx, &dis); - return (double)dis; - } - else if (type == 6) - { - return (double)((geometryData->GetElement(idx))->allowSplitting); - } - else - return (double)0; - }; -}; - -/*! -\brief The class provides mehtods for ITK - VTK mesh conversion -* -* \todo document the inner class -* \todo maybe inner class should be moved out -*/ - -template > -class MeshUtil -{ - /*! - \brief A visitor to create VTK cells by means of a class - defining the InsertImplementation interface - - The InsertImplementation interface defines the methods - \code - void InsertLine(vtkIdType *pts); - void InsertTriangle(vtkIdType *pts); - void InsertPolygon(vtkIdType npts, vtkIdType *pts); - void InsertQuad(vtkIdType *pts); - void InsertTetra(vtkIdType *pts); - void InsertHexahedron(vtkIdType *pts); - \endcode - - This class calls the appropriate insert-method of the - InsertImplementation according to the cell type of - the visited cell \em and its actual contents: e.g., - for a polygon cell with just two points, a line will - be created by calling InsertLine. - \sa ExactSwitchByCellType - \sa SingleCellArrayInsertImplementation - \sa DistributeInsertImplementation - */ - template - class SwitchByCellType : public InsertImplementation - { - // typedef the itk cells we are interested in - typedef typename itk::CellInterface - CellInterfaceType; - typedef itk::LineCell floatLineCell; - typedef itk::TriangleCell floatTriangleCell; - typedef itk::PolygonCell floatPolygonCell; - typedef itk::QuadrilateralCell floatQuadrilateralCell; - typedef itk::TetrahedronCell floatTetrahedronCell; - typedef itk::HexahedronCell floatHexahedronCell; - typedef typename CellInterfaceType::PointIdConstIterator PointIdIterator; - - public: - /*! - Visit a line and create the VTK_LINE cell - */ - void Visit(unsigned long cellId, floatLineCell *t) - { - vtkIdType pts[2]; - int i = 0; - unsigned long num = t->GetNumberOfVertices(); - vtkIdType vtkCellId = -1; - if (num == 2) - { // useless because itk::LineCell always returns 2 - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertLine((vtkIdType *)pts); - } - - if (this->m_UseCellScalarAccessor && vtkCellId >= 0) - { - this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); - } - } - - /*! - Visit a polygon and create the VTK_POLYGON cell - */ - void Visit(unsigned long cellId, floatPolygonCell *t) - { - vtkIdType pts[4096]; - int i = 0; - unsigned long num = t->GetNumberOfVertices(); - vtkIdType vtkCellId = -1; - if (num > 4096) - { - MITK_ERROR << "Problem in mitkMeshUtil: Polygon with more than maximum number of vertices encountered." - << std::endl; - } - else if (num > 3) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertPolygon(num, (vtkIdType *)pts); - } - else if (num == 3) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertTriangle((vtkIdType *)pts); - } - else if (num == 2) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertLine((vtkIdType *)pts); - } - - if (this->m_UseCellScalarAccessor && vtkCellId >= 0) - { - this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); - } - } - - /*! - Visit a triangle and create the VTK_TRIANGLE cell - */ - void Visit(unsigned long cellId, floatTriangleCell *t) - { - vtkIdType pts[3]; - int i = 0; - unsigned long num = t->GetNumberOfVertices(); - vtkIdType vtkCellId = -1; - if (num == 3) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertTriangle((vtkIdType *)pts); - } - else if (num == 2) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertLine((vtkIdType *)pts); - } - - if (this->m_UseCellScalarAccessor && vtkCellId >= 0) - { - this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); - } - } - - /*! - Visit a quad and create the VTK_QUAD cell - */ - void Visit(unsigned long cellId, floatQuadrilateralCell *t) - { - vtkIdType pts[4]; - int i = 0; - unsigned long num = t->GetNumberOfVertices(); - vtkIdType vtkCellId = -1; - if (num == 4) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - { - if (i == 2) - pts[3] = *it; - else if (i == 3) - pts[2] = *it; - else - pts[i] = *it; - i++; - // pts[i++] = *it; - } - vtkCellId = this->InsertQuad((vtkIdType *)pts); - } - else if (num == 3) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertTriangle((vtkIdType *)pts); - } - else if (num == 2) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertLine((vtkIdType *)pts); - } - - if (this->m_UseCellScalarAccessor && vtkCellId >= 0) - { - this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); - } - } - - /*! - Visit a tetrahedra and create the VTK_TETRA cell - */ - void Visit(unsigned long cellId, floatTetrahedronCell *t) - { - vtkIdType pts[4]; - int i = 0; - unsigned long num = t->GetNumberOfVertices(); - vtkIdType vtkCellId = -1; - if (num == 4) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertTetra((vtkIdType *)pts); - } - else if (num == 3) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertTriangle((vtkIdType *)pts); - } - else if (num == 2) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertLine((vtkIdType *)pts); - } - - if (this->m_UseCellScalarAccessor && vtkCellId >= 0) - { - this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); - } - } - - /*! - Visit a hexahedron and create the VTK_HEXAHEDRON cell - */ - void Visit(unsigned long cellId, floatHexahedronCell *t) - { - vtkIdType pts[8]; - int i = 0; - unsigned long num = t->GetNumberOfVertices(); - vtkIdType vtkCellId = -1; - if (num == 8) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - { - if (i == 2) - pts[i++] = *(it + 1); - else if (i == 3) - pts[i++] = *(it - 1); - else if (i == 6) - pts[i++] = *(it + 1); - else if (i == 7) - pts[i++] = *(it - 1); - else - pts[i++] = *it; - } - vtkCellId = this->InsertHexahedron((vtkIdType *)pts); - } - else if (num == 4) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertQuad((vtkIdType *)pts); - } - else if (num == 3) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertTriangle((vtkIdType *)pts); - } - else if (num == 2) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - vtkCellId = this->InsertLine((vtkIdType *)pts); - } - - if (this->m_UseCellScalarAccessor && vtkCellId >= 0) - { - this->m_CellScalars->InsertTuple1(vtkCellId, ScalarAccessor::GetCellScalar(this->m_CellData, cellId)); - } - } - }; - - /*! - \brief A visitor similar to SwitchByCellType, but with - exact matching of cell types - - Works as described in SwitchByCellType, but does exact - matching of cell types, e.g., for a polygon cell with just - two points, \em no insert-method will be called, because - a polygon must have at least three points. - \sa SwitchByCellType - \sa SingleCellArrayInsertImplementation - \sa DistributeInsertImplementation - */ - template - class ExactSwitchByCellType : public InsertImplementation - { - // typedef the itk cells we are interested in - typedef typename itk::CellInterface - CellInterfaceType; - typedef itk::LineCell floatLineCell; - typedef itk::TriangleCell floatTriangleCell; - typedef itk::PolygonCell floatPolygonCell; - typedef itk::QuadrilateralCell floatQuadrilateralCell; - typedef itk::TetrahedronCell floatTetrahedronCell; - typedef itk::HexahedronCell floatHexahedronCell; - typedef typename CellInterfaceType::PointIdConstIterator PointIdIterator; - - public: - /*! - Visit a line and create the VTK_LINE cell - */ - void Visit(unsigned long, floatLineCell *t) - { - unsigned long num = t->GetNumberOfVertices(); - vtkIdType pts[2]; - int i = 0; - - if (num == 2) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - this->InsertLine(pts); - } - } - - /*! - Visit a polygon and create the VTK_POLYGON cell - */ - void Visit(unsigned long, floatPolygonCell *t) - { - vtkIdType pts[4096]; - unsigned long num = t->GetNumberOfVertices(); - if (num > 4096) - { - MITK_ERROR << "Problem in mitkMeshUtil: Polygon with more than maximum number of vertices encountered." - << std::endl; - } - int i = 0; - - if (num > 3) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - this->InsertPolygon(num, pts); - } - } - - /*! - Visit a triangle and create the VTK_TRIANGLE cell - */ - void Visit(unsigned long, floatTriangleCell *t) - { - unsigned long num = t->GetNumberOfVertices(); - vtkIdType pts[3]; - int i = 0; - - if (num == 3) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - this->InsertTriangle(pts); - } - } - - /*! - Visit a quadrilateral and create the VTK_QUAD cell - */ - void Visit(unsigned long, floatQuadrilateralCell *t) - { - unsigned long num = t->GetNumberOfVertices(); - vtkIdType pts[4]; - int i = 0; - - if (num == 4) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - - vtkIdType tmpId = pts[2]; - pts[2] = pts[3]; - pts[3] = tmpId; - this->InsertQuad(pts); - } - } - - /*! - Visit a tetrahedron and create the VTK_TETRA cell - */ - void Visit(unsigned long, floatTetrahedronCell *t) - { - unsigned long num = t->GetNumberOfVertices(); - - vtkIdType pts[4]; - int i = 0; - - if (num == 4) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - this->InsertTetra(pts); - } - } - - /*! - Visit a hexahedron and create the VTK_HEXAHEDRON cell - */ - void Visit(unsigned long, floatHexahedronCell *t) - { - unsigned long num = t->GetNumberOfVertices(); - vtkIdType pts[8]; - int i = 0; - - if (num == 8) - { - for (PointIdIterator it = t->PointIdsBegin(); it != t->PointIdsEnd(); it++) - pts[i++] = *it; - - vtkIdType tmp[8]; - for (unsigned int i = 0; i < 8; i++) - tmp[i] = pts[i]; - pts[2] = tmp[3]; - pts[3] = tmp[2]; - pts[6] = tmp[7]; - pts[7] = tmp[6]; - this->InsertHexahedron(pts); - } - } - }; - - /*! - \brief Implementation of the InsertImplementation interface of - SwitchByCellType to define a visitor that create cells - according to their types and put them in a single - vtkCellArray (for vtkUnstructuredGrid construction) - */ - class SingleCellArrayInsertImplementation - { - vtkCellArray *m_Cells; - int *m_TypeArray; - // vtkIdType cellId; - - protected: - bool m_UseCellScalarAccessor; - vtkFloatArray *m_CellScalars; - typename MeshType::CellDataContainer::Pointer m_CellData; - - public: - SingleCellArrayInsertImplementation() : m_UseCellScalarAccessor(false) {} - /*! Set the vtkCellArray that will be constructed - */ - void SetCellArray(vtkCellArray *cells) { m_Cells = cells; } - /*! - Set the type array for storing the vtk cell types - */ - void SetTypeArray(int *i) { m_TypeArray = i; } - void SetUseCellScalarAccessor(bool flag) { m_UseCellScalarAccessor = flag; } - void SetCellScalars(vtkFloatArray *scalars) { m_CellScalars = scalars; } - vtkFloatArray *GetCellScalars() { return m_CellScalars; } - void SetMeshCellData(typename MeshType::CellDataContainer *data) { m_CellData = data; } - vtkIdType InsertLine(vtkIdType *pts) - { - vtkIdType cellId = m_Cells->InsertNextCell(2, pts); - m_TypeArray[cellId] = VTK_LINE; - return cellId; - } - - vtkIdType InsertTriangle(vtkIdType *pts) - { - vtkIdType cellId = m_Cells->InsertNextCell(3, pts); - m_TypeArray[cellId] = VTK_TRIANGLE; - return cellId; - } - - vtkIdType InsertPolygon(vtkIdType npts, vtkIdType *pts) - { - vtkIdType cellId = m_Cells->InsertNextCell(npts, pts); - m_TypeArray[cellId] = VTK_POLYGON; - return cellId; - } - - vtkIdType InsertQuad(vtkIdType *pts) - { - vtkIdType cellId = m_Cells->InsertNextCell(4, pts); - m_TypeArray[cellId] = VTK_QUAD; - return cellId; - } - - vtkIdType InsertTetra(vtkIdType *pts) - { - vtkIdType cellId = m_Cells->InsertNextCell(4, pts); - m_TypeArray[cellId] = VTK_TETRA; - return cellId; - } - - vtkIdType InsertHexahedron(vtkIdType *pts) - { - vtkIdType cellId = m_Cells->InsertNextCell(8, pts); - m_TypeArray[cellId] = VTK_HEXAHEDRON; - return cellId; - } - }; - - /*! - \brief Implementation of the InsertImplementation interface of - SwitchByCellType to define a visitor that distributes cells - according to their types (for vtkPolyData construction) - */ - class DistributeInsertImplementation - { - vtkCellArray *m_LineCells; - vtkCellArray *m_TriangleCells; - vtkCellArray *m_PolygonCells; - vtkCellArray *m_QuadCells; - - protected: - bool m_UseCellScalarAccessor; - vtkFloatArray *m_CellScalars; - typename MeshType::CellDataContainer::Pointer m_CellData; - - public: - DistributeInsertImplementation() : m_UseCellScalarAccessor(false) {} - /*! Set the vtkCellArray that will be constructed - */ - void SetCellArrays(vtkCellArray *lines, vtkCellArray *triangles, vtkCellArray *polygons, vtkCellArray *quads) - { - m_LineCells = lines; - m_TriangleCells = triangles; - m_PolygonCells = polygons; - m_QuadCells = quads; - } - - vtkIdType InsertLine(vtkIdType *pts) { return m_LineCells->InsertNextCell(2, pts); } - vtkIdType InsertTriangle(vtkIdType *pts) { return m_TriangleCells->InsertNextCell(3, pts); } - vtkIdType InsertPolygon(vtkIdType npts, vtkIdType *pts) { return m_PolygonCells->InsertNextCell(npts, pts); } - vtkIdType InsertQuad(vtkIdType *pts) { return m_QuadCells->InsertNextCell(4, pts); } - vtkIdType InsertTetra(vtkIdType * /*pts*/) { return -1; } // ignored - vtkIdType InsertHexahedron(vtkIdType * /*pts*/) { return -1; } // ignored - }; - - // typedef typename MeshType::CellType CellType; - // typedef typename itk::LineCell< CellType > LineType; - // typedef typename itk::PolygonCell< CellType > PolygonType; - // typedef typename itk::TriangleCell< CellType > TriangleType; - - typedef SwitchByCellType SingleCellArrayUserVisitorType; - typedef SwitchByCellType DistributeUserVisitorType; - typedef ExactSwitchByCellType ExactUserVisitorType; - -public: - typedef itk::MatrixOffsetTransformBase ITKTransformType; - typedef itk::MatrixOffsetTransformBase MITKTransformType; - - /*! - Convert a MITK transformation to an ITK transformation - Necessary because ITK uses double and MITK uses float values - */ - static void ConvertTransformToItk(const MITKTransformType *mitkTransform, ITKTransformType *itkTransform) - { - typename MITKTransformType::MatrixType mitkM = mitkTransform->GetMatrix(); - typename ITKTransformType::MatrixType itkM; - - typename MITKTransformType::OffsetType mitkO = mitkTransform->GetOffset(); - typename ITKTransformType::OffsetType itkO; - - for (short i = 0; i < 3; ++i) - { - for (short j = 0; j < 3; ++j) - { - itkM[i][j] = (double)mitkM[i][j]; - } - itkO[i] = (double)mitkO[i]; - } - - itkTransform->SetMatrix(itkM); - itkTransform->SetOffset(itkO); - } - - /*! - create an itkMesh object from a vtkPolyData - */ - static typename MeshType::Pointer MeshFromPolyData(vtkPolyData *poly, - mitk::BaseGeometry *geometryFrame = nullptr, - mitk::BaseGeometry *polyDataGeometryFrame = nullptr) - { - // Create a new mesh - typename MeshType::Pointer output = MeshType::New(); - output->SetCellsAllocationMethod(MeshType::CellsAllocatedDynamicallyCellByCell); - - typedef typename MeshType::CellDataContainer MeshCellDataContainerType; - - output->SetCellData(MeshCellDataContainerType::New()); - - // Get the points from vtk - vtkPoints *vtkpoints = poly->GetPoints(); - const unsigned int numPoints = poly->GetNumberOfPoints(); - - // Create a compatible point container for the mesh - // the mesh is created with a null points container - // MeshType::PointsContainer::Pointer points = - // MeshType::PointsContainer::New(); - // // Resize the point container to be able to fit the vtk points - // points->Reserve(numPoints); - // // Set the point container on the mesh - // output->SetPoints(points); - double vtkpoint[3]; - typename MeshType::PointType itkPhysicalPoint; - if (geometryFrame == nullptr) - { - if (polyDataGeometryFrame == nullptr) - { - for (unsigned int i = 0; i < numPoints; ++i) - { - vtkpoints->GetPoint(i, vtkpoint); - // MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl; - // typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i); - mitk::vtk2itk(vtkpoint, itkPhysicalPoint); - output->SetPoint(i, itkPhysicalPoint); - } - } - else - { - for (unsigned int i = 0; i < numPoints; ++i) - { - vtkpoints->GetPoint(i, vtkpoint); - // MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl; - // typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i); - mitk::Point3D mitkWorldPoint; - mitk::vtk2itk(vtkpoint, mitkWorldPoint); - polyDataGeometryFrame->IndexToWorld(mitkWorldPoint, mitkWorldPoint); - mitk::vtk2itk(mitkWorldPoint, itkPhysicalPoint); - output->SetPoint(i, itkPhysicalPoint); - } - } - } - else - { - mitk::Point3D mitkWorldPoint; - if (polyDataGeometryFrame == nullptr) - { - for (unsigned int i = 0; i < numPoints; ++i) - { - vtkpoints->GetPoint(i, vtkpoint); - // MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl; - // typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i); - mitk::vtk2itk(vtkpoint, mitkWorldPoint); - geometryFrame->WorldToItkPhysicalPoint(mitkWorldPoint, itkPhysicalPoint); - output->SetPoint(i, itkPhysicalPoint); - } - } - else - { - for (unsigned int i = 0; i < numPoints; ++i) - { - vtkpoints->GetPoint(i, vtkpoint); - // MITK_INFO << "next point: " << test[0]<< "," << test[1] << "," << test[2] << std::endl; - // typename MeshType::PixelType* apoint = (typename MeshType::PixelType*) vtkpoints->GetPoint(i); - mitk::vtk2itk(vtkpoint, mitkWorldPoint); - polyDataGeometryFrame->IndexToWorld(mitkWorldPoint, mitkWorldPoint); - geometryFrame->WorldToItkPhysicalPoint(mitkWorldPoint, itkPhysicalPoint); - output->SetPoint(i, itkPhysicalPoint); - } - } - } - - vtkCellArray *vtkcells = poly->GetPolys(); - // vtkCellArray* vtkcells = poly->GetStrips(); - // MeshType::CellsContainerPointer cells = MeshType::CellsContainer::New(); - // output->SetCells(cells); - // extract the cell id's from the vtkUnstructuredGrid - int numcells = vtkcells->GetNumberOfCells(); - int *vtkCellTypes = new int[numcells]; - int cellId = 0; - // poly ids start after verts and lines! - int cellIdOfs = poly->GetNumberOfVerts() + poly->GetNumberOfLines(); - for (; cellId < numcells; cellId++) - { - vtkCellTypes[cellId] = poly->GetCellType(cellId + cellIdOfs); - } - - // cells->Reserve(numcells); - vtkIdType npts; - vtkIdType *pts; - cellId = 0; - - typedef typename MeshType::MeshTraits OMeshTraits; - typedef typename OMeshTraits::PixelType OPixelType; - typedef typename MeshType::CellTraits CellTraits; - typedef typename itk::CellInterface CellInterfaceType; - typedef typename itk::TriangleCell TriCellType; - typedef typename TriCellType::CellAutoPointer TriCellPointer; - - TriCellPointer newCell; - output->GetCells()->Reserve(poly->GetNumberOfPolys() + poly->GetNumberOfStrips()); - output->GetCellData()->Reserve(poly->GetNumberOfPolys() + poly->GetNumberOfStrips()); - - for (vtkcells->InitTraversal(); vtkcells->GetNextCell(npts, pts); cellId++) - { - switch (vtkCellTypes[cellId]) - { - case VTK_TRIANGLE: - { - if (npts != 3) - continue; // skip non-triangles; - itk::IdentifierType pointIds[3]; - pointIds[0] = (unsigned long)pts[0]; - pointIds[1] = (unsigned long)pts[1]; - pointIds[2] = (unsigned long)pts[2]; - - newCell.TakeOwnership(new TriCellType); - newCell->SetPointIds(pointIds); //(unsigned long*)pts); - output->SetCell(cellId, newCell); - output->SetCellData(cellId, (typename MeshType::PixelType)3); - break; - } - - case VTK_QUAD: - { - if (npts != 4) - continue; // skip non-quadrilateral - itk::IdentifierType pointIds[3]; - - pointIds[0] = (unsigned long)pts[0]; - pointIds[1] = (unsigned long)pts[1]; - pointIds[2] = (unsigned long)pts[2]; - newCell.TakeOwnership(new TriCellType); - newCell->SetPointIds(pointIds); - output->SetCell(cellId, newCell); - output->SetCellData(cellId, (typename MeshType::PixelType)3); - cellId++; - - pointIds[0] = (unsigned long)pts[2]; - pointIds[1] = (unsigned long)pts[3]; - pointIds[2] = (unsigned long)pts[0]; - newCell.TakeOwnership(new TriCellType); - newCell->SetPointIds(pointIds); - output->SetCell(cellId, newCell); - output->SetCellData(cellId, (typename MeshType::PixelType)3); - break; - } - - case VTK_EMPTY_CELL: - { - if (npts != 3) - { - MITK_ERROR << "Only empty triangle cell supported by now..." << std::endl; // skip non-triangle empty cells; - continue; - } - itk::IdentifierType pointIds[3]; - pointIds[0] = (unsigned long)pts[0]; - pointIds[1] = (unsigned long)pts[1]; - pointIds[2] = (unsigned long)pts[2]; - - newCell.TakeOwnership(new TriCellType); - newCell->SetPointIds(pointIds); - output->SetCell(cellId, newCell); - output->SetCellData(cellId, (typename MeshType::PixelType)3); - break; - } - - // case VTK_VERTEX: // If need to implement use - // case VTK_POLY_VERTEX: // the poly->GetVerts() and - // case VTK_LINE: // poly->GetLines() routines - // case VTK_POLY_LINE: // outside of the switch..case. - case VTK_POLYGON: - case VTK_PIXEL: - { - if (npts != 4) - continue; // skip non-quadrilateral - itk::IdentifierType pointIds[3]; - for (unsigned int idx = 0; idx <= 1; idx++) - { - pointIds[0] = (unsigned long)pts[idx]; - pointIds[1] = (unsigned long)pts[idx + 1]; - pointIds[2] = (unsigned long)pts[idx + 2]; - newCell.TakeOwnership(new TriCellType); - newCell->SetPointIds(pointIds); - output->SetCell(cellId + idx, newCell); - output->SetCellData(cellId + idx, (typename MeshType::PixelType)3); - } - cellId++; - break; - } - - case VTK_TETRA: - case VTK_VOXEL: - case VTK_HEXAHEDRON: - case VTK_WEDGE: - case VTK_PYRAMID: - case VTK_PARAMETRIC_CURVE: - case VTK_PARAMETRIC_SURFACE: - default: - MITK_WARN << "Warning, unhandled cell type " << vtkCellTypes[cellId] << std::endl; - } - } - - if (poly->GetNumberOfStrips() != 0) - { - vtkcells = poly->GetStrips(); - numcells = vtkcells->GetNumberOfCells(); - vtkCellTypes = new int[numcells]; - int stripId = 0; - // strip ids start after verts, lines and polys! - int stripIdOfs = poly->GetNumberOfVerts() + poly->GetNumberOfLines() + poly->GetNumberOfPolys(); - for (; stripId < numcells; stripId++) - { - vtkCellTypes[stripId] = poly->GetCellType(stripId + stripIdOfs); - } - stripId = 0; - - vtkcells->InitTraversal(); - while (vtkcells->GetNextCell(npts, pts)) - { - if (vtkCellTypes[stripId] != VTK_TRIANGLE_STRIP) - { - MITK_ERROR << "Only triangle strips supported!" << std::endl; - continue; - } - stripId++; - - unsigned int numberOfTrianglesInStrip = npts - 2; - itk::IdentifierType pointIds[3]; - pointIds[0] = (unsigned long)pts[0]; - pointIds[1] = (unsigned long)pts[1]; - pointIds[2] = (unsigned long)pts[2]; - - for (unsigned int t = 0; t < numberOfTrianglesInStrip; t++) - { - newCell.TakeOwnership(new TriCellType); - newCell->SetPointIds(pointIds); - output->SetCell(cellId, newCell); - output->SetCellData(cellId, (typename MeshType::PixelType)3); - cellId++; - pointIds[0] = pointIds[1]; - pointIds[1] = pointIds[2]; - pointIds[2] = pts[t + 3]; - } - } - } - // output->Print(std::cout); - output->BuildCellLinks(); - delete[] vtkCellTypes; - return output; - } - - /*! - create an itkMesh object from an mitk::Surface - */ - static typename MeshType::Pointer MeshFromSurface(mitk::Surface *surface, mitk::BaseGeometry *geometryFrame = nullptr) - { - if (surface == nullptr) - return nullptr; - return MeshFromPolyData(surface->GetVtkPolyData(), geometryFrame, surface->GetGeometry()); - } - - /*! - create an vtkUnstructuredGrid object from an itkMesh - */ - static vtkUnstructuredGrid *MeshToUnstructuredGrid(MeshType *mesh, - bool usePointScalarAccessor = false, - bool useCellScalarAccessor = false, - unsigned int pointDataType = 0, - mitk::BaseGeometry *geometryFrame = nullptr) - { - /*! - default SingleCellArray line cell visitior definition - */ - typedef typename itk::CellInterfaceVisitorImplementation, - SingleCellArrayUserVisitorType> - SingleCellArrayLineVisitor; - - /*! - default SingleCellArray polygon cell visitior definition - */ - typedef typename itk::CellInterfaceVisitorImplementation, - SingleCellArrayUserVisitorType> - SingleCellArrayPolygonVisitor; - - /*! - default SingleCellArray triangle cell visitior definition - */ - typedef typename itk::CellInterfaceVisitorImplementation< - typename MeshType::CellPixelType, - typename MeshType::CellTraits, - itk::TriangleCell>, - SingleCellArrayUserVisitorType> - SingleCellArrayTriangleVisitor; - - /*! - default SingleCellArray quad cell visitior definition - */ - typedef typename itk::CellInterfaceVisitorImplementation< - typename MeshType::CellPixelType, - typename MeshType::CellTraits, - itk::QuadrilateralCell>, - SingleCellArrayUserVisitorType> - SingleCellArrayQuadrilateralVisitor; - - /*! - default SingleCellArray tetra cell visitior definition - */ - typedef typename itk::CellInterfaceVisitorImplementation< - typename MeshType::CellPixelType, - typename MeshType::CellTraits, - itk::TetrahedronCell>, - SingleCellArrayUserVisitorType> - SingleCellArrayTetrahedronVisitor; - - /*! - default SingleCellArray hex cell visitior definition - */ - typedef typename itk::CellInterfaceVisitorImplementation< - typename MeshType::CellPixelType, - typename MeshType::CellTraits, - itk::HexahedronCell>, - SingleCellArrayUserVisitorType> - SingleCellArrayHexahedronVisitor; - - // Get the number of points in the mesh - int numPoints = mesh->GetNumberOfPoints(); - if (numPoints == 0) - { - // mesh->Print(std::cerr); - MITK_FATAL << "no points in Grid " << std::endl; - exit(-1); - } - // Create a vtkUnstructuredGrid - vtkUnstructuredGrid *vgrid = vtkUnstructuredGrid::New(); - // Create the vtkPoints object and set the number of points - vtkPoints *vpoints = vtkPoints::New(VTK_DOUBLE); - - vtkFloatArray *pointScalars = vtkFloatArray::New(); - vtkFloatArray *cellScalars = vtkFloatArray::New(); - pointScalars->SetNumberOfComponents(1); - cellScalars->SetNumberOfComponents(1); - - typename MeshType::PointsContainer::Pointer points = mesh->GetPoints(); - typename MeshType::PointsContainer::Iterator i; - - // iterate over all the points in the itk mesh to find - // the maximal index - unsigned int maxIndex = 0; - for (i = points->Begin(); i != points->End(); ++i) - { - if (maxIndex < i->Index()) - maxIndex = i->Index(); - } - - // initialize vtk-classes for points and scalars - vpoints->SetNumberOfPoints(maxIndex + 1); - pointScalars->SetNumberOfTuples(maxIndex + 1); - cellScalars->SetNumberOfTuples(mesh->GetNumberOfCells()); - - double vtkpoint[3]; - typename MeshType::PointType itkPhysicalPoint; - if (geometryFrame == nullptr) - { - for (i = points->Begin(); i != points->End(); ++i) - { - // Get the point index from the point container iterator - int idx = i->Index(); - - itkPhysicalPoint = i->Value(); - mitk::itk2vtk(itkPhysicalPoint, vtkpoint); - // Set the vtk point at the index with the the coord array from itk - vpoints->SetPoint(idx, vtkpoint); - - if (usePointScalarAccessor) - { - pointScalars->InsertTuple1( - idx, ScalarAccessor::GetPointScalar(mesh->GetPointData(), i->Index(), mesh, pointDataType)); - } - } - } - else - { - mitk::Point3D mitkWorldPoint; - for (i = points->Begin(); i != points->End(); ++i) - { - // Get the point index from the point container iterator - int idx = i->Index(); - - itkPhysicalPoint = i->Value(); - geometryFrame->ItkPhysicalPointToWorld(itkPhysicalPoint, mitkWorldPoint); - mitk::itk2vtk(mitkWorldPoint, vtkpoint); - // Set the vtk point at the index with the the coord array from itk - vpoints->SetPoint(idx, vtkpoint); - - if (usePointScalarAccessor) - { - pointScalars->InsertTuple1( - idx, ScalarAccessor::GetPointScalar(mesh->GetPointData(), i->Index(), mesh, pointDataType)); - } - } - } - // Set the points on the vtk grid - vgrid->SetPoints(vpoints); - if (usePointScalarAccessor) - vgrid->GetPointData()->SetScalars(pointScalars); - - // Now create the cells using the MultiVisitor - // 1. Create a MultiVisitor - typename MeshType::CellType::MultiVisitor::Pointer mv = MeshType::CellType::MultiVisitor::New(); - // 2. Create visitors - typename SingleCellArrayLineVisitor::Pointer lv = SingleCellArrayLineVisitor::New(); - typename SingleCellArrayPolygonVisitor::Pointer pv = SingleCellArrayPolygonVisitor::New(); - typename SingleCellArrayTriangleVisitor::Pointer tv = SingleCellArrayTriangleVisitor::New(); - typename SingleCellArrayQuadrilateralVisitor::Pointer qv = SingleCellArrayQuadrilateralVisitor::New(); - typename SingleCellArrayTetrahedronVisitor::Pointer tetv = SingleCellArrayTetrahedronVisitor::New(); - typename SingleCellArrayHexahedronVisitor::Pointer hv = SingleCellArrayHexahedronVisitor::New(); - // 3. Set up the visitors - // int vtkCellCount = 0; // running counter for current cell being inserted into vtk - int numCells = mesh->GetNumberOfCells(); - int *types = new int[numCells]; // type array for vtk - // create vtk cells and estimate the size - vtkCellArray *cells = vtkCellArray::New(); - cells->Allocate(numCells); - // Set the TypeArray CellCount and CellArray for the visitors - lv->SetTypeArray(types); - lv->SetCellArray(cells); - pv->SetTypeArray(types); - pv->SetCellArray(cells); - tv->SetTypeArray(types); - // tv->SetCellCounter(&vtkCellCount); - tv->SetCellArray(cells); - qv->SetTypeArray(types); - // qv->SetCellCounter(&vtkCellCount); - qv->SetCellArray(cells); - tetv->SetTypeArray(types); - tetv->SetCellArray(cells); - hv->SetTypeArray(types); - hv->SetCellArray(cells); - - if (useCellScalarAccessor) - { - lv->SetUseCellScalarAccessor(true); - lv->SetCellScalars(cellScalars); - lv->SetMeshCellData(mesh->GetCellData()); - - pv->SetUseCellScalarAccessor(true); - pv->SetCellScalars(cellScalars); - pv->SetMeshCellData(mesh->GetCellData()); - - tv->SetUseCellScalarAccessor(true); - tv->SetCellScalars(cellScalars); - tv->SetMeshCellData(mesh->GetCellData()); - - qv->SetUseCellScalarAccessor(true); - qv->SetCellScalars(cellScalars); - qv->SetMeshCellData(mesh->GetCellData()); - - tetv->SetUseCellScalarAccessor(true); - tetv->SetCellScalars(cellScalars); - tetv->SetMeshCellData(mesh->GetCellData()); - - hv->SetUseCellScalarAccessor(true); - hv->SetCellScalars(cellScalars); - hv->SetMeshCellData(mesh->GetCellData()); - } - - // add the visitors to the multivisitor - mv->AddVisitor(lv); - mv->AddVisitor(pv); - mv->AddVisitor(tv); - mv->AddVisitor(qv); - mv->AddVisitor(tetv); - mv->AddVisitor(hv); - // Now ask the mesh to accept the multivisitor which - // will Call Visit for each cell in the mesh that matches the - // cell types of the visitors added to the MultiVisitor - mesh->Accept(mv); - // Now set the cells on the vtk grid with the type array and cell array - - vgrid->SetCells(types, cells); - vgrid->GetCellData()->SetScalars(cellScalars); - - // Clean up vtk objects (no vtkSmartPointer ... ) - cells->Delete(); - vpoints->Delete(); - delete[] types; - - pointScalars->Delete(); - cellScalars->Delete(); - // MITK_INFO << "meshToUnstructuredGrid end" << std::endl; - return vgrid; - } - - /*! - create a vtkPolyData object from an itkMesh - */ - static vtkPolyData *MeshToPolyData(MeshType *mesh, - bool onlyTriangles = false, - bool useScalarAccessor = false, - unsigned int pointDataType = 0, - mitk::BaseGeometry *geometryFrame = nullptr, - vtkPolyData *polydata = nullptr) - { - /*! - default Distribute line cell visitior definition - */ - typedef typename itk::CellInterfaceVisitorImplementation, - DistributeUserVisitorType> - DistributeLineVisitor; - - /*! - default Distribute polygon cell visitior definition - */ - typedef typename itk::CellInterfaceVisitorImplementation, - DistributeUserVisitorType> - DistributePolygonVisitor; - - /*! - default Distribute triangle cell visitior definition - */ - typedef typename itk::CellInterfaceVisitorImplementation< - typename MeshType::CellPixelType, - typename MeshType::CellTraits, - itk::TriangleCell>, - DistributeUserVisitorType> - DistributeTriangleVisitor; - - /*! - default Distribute quad cell visitior definition - */ - typedef typename itk::CellInterfaceVisitorImplementation< - typename MeshType::CellPixelType, - typename MeshType::CellTraits, - itk::QuadrilateralCell>, - DistributeUserVisitorType> - DistributeQuadrilateralVisitor; - - /*! - default Distribute triangle cell visitior definition - */ - typedef typename itk::CellInterfaceVisitorImplementation< - typename MeshType::CellPixelType, - typename MeshType::CellTraits, - itk::TriangleCell>, - ExactUserVisitorType> - ExactTriangleVisitor; - - // Get the number of points in the mesh - int numPoints = mesh->GetNumberOfPoints(); - if (numPoints == 0) - { - // mesh->Print(std::cerr); - MITK_ERROR << "no points in Grid " << std::endl; - } - // Create a vtkPolyData - if (polydata == nullptr) - polydata = vtkPolyData::New(); - else - polydata->Initialize(); - - // Create the vtkPoints object and set the number of points - vtkPoints *vpoints = vtkPoints::New(VTK_DOUBLE); - - vtkFloatArray *scalars = vtkFloatArray::New(); - scalars->SetNumberOfComponents(1); - - typename MeshType::PointsContainer::Pointer points = mesh->GetPoints(); - typename MeshType::PointsContainer::Iterator i; - - // iterate over all the points in the itk mesh to find - // the maximal index - unsigned int maxIndex = 0; - for (i = points->Begin(); i != points->End(); ++i) - { - if (maxIndex < i->Index()) - maxIndex = i->Index(); - } - - // initialize vtk-classes for points and scalars - vpoints->SetNumberOfPoints(maxIndex + 1); - scalars->SetNumberOfTuples(maxIndex + 1); - - // iterate over all the points in the itk mesh filling in - // the vtkPoints object as we go - - double vtkpoint[3]; - typename MeshType::PointType itkPhysicalPoint; - if (geometryFrame == nullptr) - { - for (i = points->Begin(); i != points->End(); ++i) - { - // Get the point index from the point container iterator - int idx = i->Index(); - - itkPhysicalPoint = i->Value(); - mitk::itk2vtk(itkPhysicalPoint, vtkpoint); - // Set the vtk point at the index with the the coord array from itk - // itk returns a const pointer, but vtk is not const correct, so - // we have to use a const cast to get rid of the const - // vpoints->SetPoint(idx, const_cast(i->Value().GetDataPointer())); - vpoints->SetPoint(idx, vtkpoint); - - if (useScalarAccessor) - { - scalars->InsertTuple1(idx, - ScalarAccessor::GetPointScalar(mesh->GetPointData(), i->Index(), mesh, pointDataType)); - } - } - } - else - { - mitk::Point3D mitkWorldPoint; - for (i = points->Begin(); i != points->End(); ++i) - { - // Get the point index from the point container iterator - int idx = i->Index(); - - itkPhysicalPoint = i->Value(); - geometryFrame->ItkPhysicalPointToWorld(itkPhysicalPoint, mitkWorldPoint); - mitk::itk2vtk(mitkWorldPoint, vtkpoint); - // Set the vtk point at the index with the the coord array from itk - // itk returns a const pointer, but vtk is not const correct, so - // we have to use a const cast to get rid of the const - // vpoints->SetPoint(idx, const_cast(i->Value().GetDataPointer())); - vpoints->SetPoint(idx, vtkpoint); - - if (useScalarAccessor) - { - scalars->InsertTuple1(idx, - ScalarAccessor::GetPointScalar(mesh->GetPointData(), i->Index(), mesh, pointDataType)); - } - } - } - - // Set the points on the vtk grid - polydata->SetPoints(vpoints); - if (useScalarAccessor) - polydata->GetPointData()->SetScalars(scalars); - polydata->GetPointData()->CopyAllOn(); - - // Now create the cells using the MulitVisitor - // 1. Create a MultiVisitor - typedef typename MeshType::CellType::MultiVisitor MeshMV; - typename MeshMV::Pointer mv = MeshMV::New(); - - int numCells = mesh->GetNumberOfCells(); - - if (onlyTriangles) - { - // create vtk cells and allocate - vtkCellArray *trianglecells = vtkCellArray::New(); - trianglecells->Allocate(numCells); - - // 2. Create a triangle visitor and add it to the multivisitor - typename ExactTriangleVisitor::Pointer tv = ExactTriangleVisitor::New(); - tv->SetCellArrays(nullptr, trianglecells, nullptr, nullptr); - mv->AddVisitor(tv); - // 3. Now ask the mesh to accept the multivisitor which - // will Call Visit for each cell in the mesh that matches the - // cell types of the visitors added to the MultiVisitor - mesh->Accept(mv); - - // 4. Set the result into our vtkPolyData - if (trianglecells->GetNumberOfCells() > 0) - polydata->SetStrips(trianglecells); - - // 5. Clean up vtk objects (no vtkSmartPointer ... ) - trianglecells->Delete(); - } - else - { - // create vtk cells and allocate - vtkCellArray *linecells = vtkCellArray::New(); - vtkCellArray *trianglecells = vtkCellArray::New(); - vtkCellArray *polygoncells = vtkCellArray::New(); - linecells->Allocate(numCells); - trianglecells->Allocate(numCells); - polygoncells->Allocate(numCells); - - // 2. Create visitors - typename DistributeLineVisitor::Pointer lv = DistributeLineVisitor::New(); - typename DistributePolygonVisitor::Pointer pv = DistributePolygonVisitor::New(); - typename DistributeTriangleVisitor::Pointer tv = DistributeTriangleVisitor::New(); - typename DistributeQuadrilateralVisitor::Pointer qv = DistributeQuadrilateralVisitor::New(); - - lv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells); - pv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells); - tv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells); - qv->SetCellArrays(linecells, trianglecells, polygoncells, polygoncells); - - // add the visitors to the multivisitor - mv->AddVisitor(tv); - mv->AddVisitor(lv); - mv->AddVisitor(pv); - mv->AddVisitor(qv); - // 3. Now ask the mesh to accept the multivisitor which - // will Call Visit for each cell in the mesh that matches the - // cell types of the visitors added to the MultiVisitor - mesh->Accept(mv); - - // 4. Set the result into our vtkPolyData - if (linecells->GetNumberOfCells() > 0) - polydata->SetLines(linecells); - if (trianglecells->GetNumberOfCells() > 0) - polydata->SetStrips(trianglecells); - if (polygoncells->GetNumberOfCells() > 0) - polydata->SetPolys(polygoncells); - - // 5. Clean up vtk objects (no vtkSmartPointer ... ) - linecells->Delete(); - trianglecells->Delete(); - polygoncells->Delete(); - } - vpoints->Delete(); - scalars->Delete(); - - // MITK_INFO << "meshToPolyData end" << std::endl; - return polydata; - } - - static typename MeshType::Pointer CreateRegularSphereMesh(typename MeshType::PointType center, - typename MeshType::PointType::VectorType scale, - int resolution) - { - typedef itk::RegularSphereMeshSource SphereSourceType; - typename SphereSourceType::Pointer mySphereSource = SphereSourceType::New(); - - mySphereSource->SetCenter(center); - mySphereSource->SetScale(scale); - mySphereSource->SetResolution(resolution); - mySphereSource->Update(); - - typename MeshType::Pointer resultMesh = mySphereSource->GetOutput(); - resultMesh->Register(); // necessary ???? - return resultMesh; - } - - static typename MeshType::Pointer CreateSphereMesh(typename MeshType::PointType center, - typename MeshType::PointType scale, - int *resolution) - { - typedef typename itk::SphereMeshSource SphereSource; - - typename SphereSource::Pointer mySphereSource = SphereSource::New(); - - mySphereSource->SetCenter(center); - mySphereSource->SetScale(scale); - mySphereSource->SetResolutionX(resolution[0]); - mySphereSource->SetResolutionY(resolution[1]); - mySphereSource->SetSquareness1(1); - mySphereSource->SetSquareness2(1); - mySphereSource->Update(); - mySphereSource->GetOutput(); - - typename MeshType::Pointer resultMesh = mySphereSource->GetOutput(); - resultMesh->Register(); - - return resultMesh; - } - - // static typename MeshType::Pointer TranslateMesh(typename MeshType::PointType vec, MeshType* input) - // { - // - // typename MeshType::Pointer output = MeshType::New(); - // { - // output->SetPoints(input->GetPoints()); - // output->SetPointData(input->GetPointData()); - // output->SetCells(input->GetCells()); - // output->SetLastCellId( input->GetLastCellId() ); - // typename MeshType::GeometryMapIterator pointDataIterator = input->GetGeometryData()->Begin(); - // typename MeshType::GeometryMapIterator pointDataEnd = input->GetGeometryData()->End(); - // - // typename MeshType::PointType inputPoint,outputPoint; - // - // while (pointDataIterator != pointDataEnd) - // { - // unsigned long pointId = pointDataIterator->Index(); - // itk::SimplexMeshGeometry* newGeometry = new itk::SimplexMeshGeometry(); - // itk::SimplexMeshGeometry* refGeometry = pointDataIterator->Value(); - // - // input->GetPoint(pointId, &inputPoint ); - // outputPoint[0] = inputPoint[0] + vec[0]; - // outputPoint[1] = inputPoint[1] + vec[1]; - // outputPoint[2] = inputPoint[2] + vec[2]; - // output->SetPoint( pointId, outputPoint ); - // - // - // newGeometry->pos = outputPoint; - // newGeometry->neighborIndices = refGeometry->neighborIndices; - // newGeometry->meanCurvature = refGeometry->meanCurvature; - // newGeometry->neighbors = refGeometry->neighbors; - // newGeometry->oldPos = refGeometry->oldPos; - // newGeometry->eps = refGeometry->eps; - // newGeometry->referenceMetrics = refGeometry->referenceMetrics; - // newGeometry->neighborSet = refGeometry->neighborSet; - // newGeometry->distance = refGeometry->distance; - // newGeometry->externalForce = refGeometry->externalForce; - // newGeometry->internalForce = refGeometry->internalForce; - // output->SetGeometryData(pointId, newGeometry); - // pointDataIterator++; - // } - // } - //// output->SetGeometryData( inputMesh->GetGeometryData() ); - // return output; - // } - - static typename MeshType::Pointer CreateRegularSphereMesh2(typename MeshType::PointType center, - typename MeshType::PointType scale, - int resolution) - { - typedef typename itk::AutomaticTopologyMeshSource MeshSourceType; - typename MeshSourceType::Pointer mySphereSource = MeshSourceType::New(); - - typename MeshType::PointType pnt0, pnt1, pnt2, pnt3, pnt4, pnt5, pnt6, pnt7, pnt8, pnt9, pnt10, pnt11; - double c1 = 0.5 * (1.0 + sqrt(5.0)); - double c2 = 1.0; - double len = sqrt(c1 * c1 + c2 * c2); - c1 /= len; - c2 /= len; - - pnt0[0] = center[0] - c1 * scale[0]; - pnt0[1] = center[1]; - pnt0[2] = center[2] + c2 * scale[2]; - pnt1[0] = center[0]; - pnt1[1] = center[1] + c2 * scale[1]; - pnt1[2] = center[2] - c1 * scale[2]; - pnt2[0] = center[0]; - pnt2[1] = center[1] + c2 * scale[1]; - pnt2[2] = center[2] + c1 * scale[2]; - pnt3[0] = center[0] + c1 * scale[0]; - pnt3[1] = center[1]; - pnt3[2] = center[2] - c2 * scale[2]; - pnt4[0] = center[0] - c2 * scale[0]; - pnt4[1] = center[1] - c1 * scale[1]; - pnt4[2] = center[2]; - pnt5[0] = center[0] - c2 * scale[0]; - pnt5[1] = center[1] + c1 * scale[1]; - pnt5[2] = center[2]; - pnt6[0] = center[0]; - pnt6[1] = center[1] - c2 * scale[1]; - pnt6[2] = center[2] + c1 * scale[2]; - pnt7[0] = center[0] + c2 * scale[0]; - pnt7[1] = center[1] + c1 * scale[1]; - pnt7[2] = center[2]; - pnt8[0] = center[0]; - pnt8[1] = center[1] - c2 * scale[1]; - pnt8[2] = center[2] - c1 * scale[2]; - pnt9[0] = center[0] + c1 * scale[0]; - pnt9[1] = center[1]; - pnt9[2] = center[2] + c2 * scale[2]; - pnt10[0] = center[0] + c2 * scale[0]; - pnt10[1] = center[1] - c1 * scale[1]; - pnt10[2] = center[2]; - pnt11[0] = center[0] - c1 * scale[0]; - pnt11[1] = center[1]; - pnt11[2] = center[2] - c2 * scale[2]; - - addTriangle(mySphereSource, scale, pnt9, pnt2, pnt6, resolution); - addTriangle(mySphereSource, scale, pnt1, pnt11, pnt5, resolution); - addTriangle(mySphereSource, scale, pnt11, pnt1, pnt8, resolution); - addTriangle(mySphereSource, scale, pnt0, pnt11, pnt4, resolution); - addTriangle(mySphereSource, scale, pnt3, pnt1, pnt7, resolution); - addTriangle(mySphereSource, scale, pnt3, pnt8, pnt1, resolution); - addTriangle(mySphereSource, scale, pnt9, pnt3, pnt7, resolution); - addTriangle(mySphereSource, scale, pnt0, pnt6, pnt2, resolution); - addTriangle(mySphereSource, scale, pnt4, pnt10, pnt6, resolution); - addTriangle(mySphereSource, scale, pnt1, pnt5, pnt7, resolution); - addTriangle(mySphereSource, scale, pnt7, pnt5, pnt2, resolution); - addTriangle(mySphereSource, scale, pnt8, pnt3, pnt10, resolution); - addTriangle(mySphereSource, scale, pnt4, pnt11, pnt8, resolution); - addTriangle(mySphereSource, scale, pnt9, pnt7, pnt2, resolution); - addTriangle(mySphereSource, scale, pnt10, pnt9, pnt6, resolution); - addTriangle(mySphereSource, scale, pnt0, pnt5, pnt11, resolution); - addTriangle(mySphereSource, scale, pnt0, pnt2, pnt5, resolution); - addTriangle(mySphereSource, scale, pnt8, pnt10, pnt4, resolution); - addTriangle(mySphereSource, scale, pnt3, pnt9, pnt10, resolution); - addTriangle(mySphereSource, scale, pnt6, pnt0, pnt4, resolution); - - return mySphereSource->GetOutput(); - } - -private: - static void addTriangle(typename itk::AutomaticTopologyMeshSource::Pointer meshSource, - typename MeshType::PointType scale, - typename MeshType::PointType pnt0, - typename MeshType::PointType pnt1, - typename MeshType::PointType pnt2, - int resolution) - { - if (resolution == 0) - { - // add triangle - meshSource->AddTriangle(meshSource->AddPoint(pnt0), meshSource->AddPoint(pnt1), meshSource->AddPoint(pnt2)); - } - else - { - vnl_vector_fixed v1, v2, res, pv; - v1 = (pnt1 - pnt0).Get_vnl_vector(); - v2 = (pnt2 - pnt0).Get_vnl_vector(); - res = vnl_cross_3d(v1, v2); - pv = pnt0.GetVectorFromOrigin().Get_vnl_vector(); - // double d = res[0]*pv[0] + res[1]*pv[1] + res[2]*pv[2]; - - // subdivision - typename MeshType::PointType pnt01, pnt12, pnt20; - for (int d = 0; d < 3; d++) - { - pnt01[d] = (pnt0[d] + pnt1[d]) / 2.0; - pnt12[d] = (pnt1[d] + pnt2[d]) / 2.0; - pnt20[d] = (pnt2[d] + pnt0[d]) / 2.0; - } - // map new points to sphere - double lenPnt01 = 0; - for (int d = 0; d < 3; d++) - lenPnt01 += pnt01[d] * pnt01[d]; - lenPnt01 = sqrt(lenPnt01); - double lenPnt12 = 0; - for (int d = 0; d < 3; d++) - lenPnt12 += pnt12[d] * pnt12[d]; - lenPnt12 = sqrt(lenPnt12); - double lenPnt20 = 0; - for (int d = 0; d < 3; d++) - lenPnt20 += pnt20[d] * pnt20[d]; - lenPnt20 = sqrt(lenPnt20); - for (int d = 0; d < 3; d++) - { - pnt01[d] *= scale[d] / lenPnt01; - pnt12[d] *= scale[d] / lenPnt12; - pnt20[d] *= scale[d] / lenPnt20; - } - addTriangle(meshSource, scale, pnt0, pnt01, pnt20, resolution - 1); - addTriangle(meshSource, scale, pnt01, pnt1, pnt12, resolution - 1); - addTriangle(meshSource, scale, pnt20, pnt12, pnt2, resolution - 1); - addTriangle(meshSource, scale, pnt01, pnt12, pnt20, resolution - 1); - } - } -}; - -#endif // MITKMESHUTIL_H_INCLUDED diff --git a/Modules/DataTypesExt/src/mitkMesh.cpp b/Modules/DataTypesExt/src/mitkMesh.cpp deleted file mode 100644 index b88524fc13..0000000000 --- a/Modules/DataTypesExt/src/mitkMesh.cpp +++ /dev/null @@ -1,805 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#include "mitkMesh.h" -#include "mitkInteractionConst.h" -#include "mitkLine.h" -#include "mitkLineOperation.h" -#include "mitkLineOperation.h" -#include "mitkNumericTypes.h" -#include "mitkOperation.h" -#include "mitkOperationActor.h" -#include "mitkPointOperation.h" -#include "mitkRenderingManager.h" -#include "mitkStatusBar.h" - -mitk::Mesh::Mesh() -{ -} - -mitk::Mesh::~Mesh() -{ -} - -const mitk::Mesh::DataType *mitk::Mesh::GetMesh(int t) const -{ - return m_PointSetSeries[t]; -} - -mitk::Mesh::DataType *mitk::Mesh::GetMesh(int t) -{ - return m_PointSetSeries[t]; -} - -void mitk::Mesh::SetMesh(DataType *mesh, int t) -{ - this->Expand(t + 1); - m_PointSetSeries[t] = mesh; -} - -unsigned long mitk::Mesh::GetNumberOfCells(int t) -{ - return m_PointSetSeries[t]->GetNumberOfCells(); -} - -// search a line that is close enough according to the given position -bool mitk::Mesh::SearchLine(Point3D point, float distance, unsigned long &lineId, unsigned long &cellId, int t) -{ - // returns true if a line is found - ScalarType bestDist = distance; - - // iterate through all cells. - ConstCellIterator cellIt = m_PointSetSeries[t]->GetCells()->Begin(); - ConstCellIterator cellEnd = m_PointSetSeries[t]->GetCells()->End(); - while (cellIt != cellEnd) - { - if (cellIt.Value()->GetNumberOfPoints() > 1) - { - // then iterate through all indexes of points in it->Value() - PointIdIterator inAIt = cellIt.Value()->PointIdsBegin(); // first point - PointIdIterator inBIt = cellIt.Value()->PointIdsBegin(); // second point - PointIdIterator inEnd = cellIt.Value()->PointIdsEnd(); - - ++inAIt; // so it points to the point before inBIt - - int currentLineId = 0; - while (inAIt != inEnd) - { - mitk::PointSet::PointType pointA, pointB; - if (m_PointSetSeries[t]->GetPoint((*inAIt), &pointA) && m_PointSetSeries[t]->GetPoint((*inBIt), &pointB)) - { - auto line = new Line(); - line->SetPoints(pointA, pointB); - double thisDistance = line->Distance(point); - if (thisDistance < bestDist) - { - cellId = cellIt->Index(); - lineId = currentLineId; - bestDist = thisDistance; - } - } - ++inAIt; - ++inBIt; - ++currentLineId; - } - - // If the cell is closed, then check the line from the last index to - // the first index if inAIt points to inEnd, then inBIt points to the - // last index. - CellDataType cellData; - bool dataOk = m_PointSetSeries[t]->GetCellData(cellIt->Index(), &cellData); - if (dataOk) - { - if (cellData.closed) - { - // get the points - PointIdIterator inAIt = cellIt.Value()->PointIdsBegin(); // first point - // inBIt points to last. - mitk::PointSet::PointType pointA, pointB; - if (m_PointSetSeries[t]->GetPoint((*inAIt), &pointA) && m_PointSetSeries[t]->GetPoint((*inBIt), &pointB)) - { - auto line = new Line(); - line->SetPoints(pointA, pointB); - double thisDistance = line->Distance(point); - if (thisDistance < bestDist) - { - cellId = cellIt->Index(); - lineId = currentLineId; - bestDist = thisDistance; - } - } - } - } - } - ++cellIt; - } - return (bestDist < distance); -} - -int mitk::Mesh::SearchFirstCell(unsigned long pointId, int t) -{ - // iterate through all cells and find the cell the given pointId is inside - ConstCellIterator it = m_PointSetSeries[t]->GetCells()->Begin(); - ConstCellIterator end = m_PointSetSeries[t]->GetCells()->End(); - while (it != end) - { - PointIdIterator position = std::find(it->Value()->PointIdsBegin(), it->Value()->PointIdsEnd(), pointId); - - if (position != it->Value()->PointIdsEnd()) - { - return it->Index(); - } - ++it; - } - return -1; -} - -// Due to not implemented itk::CellInterface::EvaluatePosition and errors in -// using vtkCell::EvaluatePosition (changing iterator!) we must implement -// it in mitk::Mesh -// make it easy and look for hit points and hit lines: needs to be done anyway! -bool mitk::Mesh::EvaluatePosition(mitk::Point3D point, unsigned long &cellId, float precision, int t) -{ - int pointId = this->SearchPoint(point, precision, t); - if (pointId > -1) - { - // search the cell the point lies inside - cellId = this->SearchFirstCell(pointId, t); - return true; - } - unsigned long lineId = 0; - if (this->SearchLine(point, precision, lineId, cellId, t)) - { - return true; - } - - return false; -} - -unsigned long mitk::Mesh::GetNewCellId(int t) -{ - long nextCellId = -1; - ConstCellIterator it = m_PointSetSeries[t]->GetCells()->Begin(); - ConstCellIterator end = m_PointSetSeries[t]->GetCells()->End(); - - while (it != end) - { - nextCellId = it.Index(); - ++it; - } - ++nextCellId; - return nextCellId; -} - -int mitk::Mesh::SearchSelectedCell(int t) -{ - CellDataIterator cellDataIt, cellDataEnd; - cellDataEnd = m_PointSetSeries[t]->GetCellData()->End(); - for (cellDataIt = m_PointSetSeries[t]->GetCellData()->Begin(); cellDataIt != cellDataEnd; cellDataIt++) - { - // then declare an operation which unselects this line; UndoOperation as well! - if (cellDataIt->Value().selected) - { - return cellDataIt->Index(); - } - } - return -1; -} - -// get the cell; then iterate through the Ids times lineId. Then IdA ist the -// one, IdB ist ne next.don't forget the last closing line if the cell is -// closed -bool mitk::Mesh::GetPointIds(unsigned long cellId, unsigned long lineId, int &idA, int &idB, int t) -{ - CellAutoPointer cellAutoPointer; - bool ok = m_PointSetSeries[t]->GetCell(cellId, cellAutoPointer); - if (ok) - { - CellType *cell = cellAutoPointer.GetPointer(); - - // Get the cellData to also check the closing line - CellDataType cellData; - m_PointSetSeries[t]->GetCellData(cellId, &cellData); - bool closed = cellData.closed; - - PointIdIterator pointIdIt = cell->PointIdsBegin(); - PointIdIterator pointIdEnd = cell->PointIdsEnd(); - unsigned int counter = 0; - bool found = false; - while (pointIdIt != pointIdEnd) - { - if (counter == lineId) - { - idA = (*pointIdIt); - ++pointIdIt; - found = true; - break; - } - ++counter; - ++pointIdIt; - } - if (found) - { - // if in the middle - if (pointIdIt != pointIdEnd) - { - idB = (*pointIdIt); - } - // if found but on the end, then it is the closing connection, so the - // last and the first point - else if (closed) - { - pointIdIt = cell->PointIdsBegin(); - idB = (*pointIdIt); - } - } - else - ok = false; - } - return ok; -} - -void mitk::Mesh::ExecuteOperation(Operation *operation) -{ - // adding only the operations, that aren't implemented by the pointset. - switch (operation->GetOperationType()) - { - case OpNOTHING: - break; - - case OpNEWCELL: - { - auto *lineOp = dynamic_cast(operation); - - // if no lineoperation, then call superclass pointSet - if (lineOp == nullptr) - { - Superclass::ExecuteOperation(operation); - } - - bool ok; - int cellId = lineOp->GetCellId(); - CellAutoPointer cellAutoPointer; - ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); - - // if it doesn't already exist - if (!ok) - { - cellAutoPointer.TakeOwnership(new PolygonType); - m_PointSetSeries[0]->SetCell(cellId, cellAutoPointer); - CellDataType cellData; - cellData.selected = true; - cellData.selectedLines.clear(); - cellData.closed = false; - m_PointSetSeries[0]->SetCellData(cellId, cellData); - } - } - break; - - case OpDELETECELL: - { - auto *lineOp = dynamic_cast(operation); - if (lineOp == nullptr) // if no lineoperation, then call superclass pointSet - { - Superclass::ExecuteOperation(operation); - } - m_PointSetSeries[0]->GetCells()->DeleteIndex((unsigned)lineOp->GetCellId()); - m_PointSetSeries[0]->GetCellData()->DeleteIndex((unsigned)lineOp->GetCellId()); - } - break; - - case OpCLOSECELL: - // sets the bolean flag closed from a specified cell to true. - { - auto *lineOp = dynamic_cast(operation); - if (lineOp == nullptr) // if no lineoperation, then call superclass pointSet - { - // then search the selected cell!//TODO - Superclass::ExecuteOperation(operation); - } - bool ok; - int cellId = lineOp->GetCellId(); - if (cellId < 0) // cellId isn't set - { - cellId = this->SearchSelectedCell(0); - if (cellId < 0) // still not found - return; - } - CellAutoPointer cellAutoPointer; - - // get directly the celldata!TODO - ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); - if (ok) - { - CellDataType cellData; - m_PointSetSeries[0]->GetCellData(cellId, &cellData); - cellData.closed = true; - m_PointSetSeries[0]->SetCellData(cellId, cellData); - } - } - break; - - case OpOPENCELL: - { - auto *lineOp = dynamic_cast(operation); - if (lineOp == nullptr) // if no lineoperation, then call superclass pointSet - { - Superclass::ExecuteOperation(operation); - } - bool ok; - int cellId = lineOp->GetCellId(); - CellAutoPointer cellAutoPointer; - ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); - if (ok) - { - CellDataType cellData; - m_PointSetSeries[0]->GetCellData(cellId, &cellData); - cellData.closed = false; - ; - m_PointSetSeries[0]->SetCellData(cellId, cellData); - } - } - break; - - case OpADDLINE: - // inserts the ID of the selected point into the indexes of lines in the - // selected cell afterwars the added line is selected - { - auto *lineOp = dynamic_cast(operation); - - int cellId = -1; - int pId = -1; - - if (lineOp == nullptr) - { - cellId = this->SearchSelectedCell(0); - if (cellId == -1) - return; - - pId = this->SearchSelectedPoint(0); - if (pId == -1) - return; - } - else - { - cellId = lineOp->GetCellId(); - if (cellId == -1) - return; - pId = lineOp->GetPIdA(); - if (pId == -1) - return; - } - - bool ok; - CellAutoPointer cellAutoPointer; - ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); - if (ok) - { - CellType *cell = cellAutoPointer.GetPointer(); - if (cell->GetType() == CellType::POLYGON_CELL) - { - auto *polygon = static_cast(cell); - // add the pointId to the Cell. filling the empty cell with - // one id doesn't mean to add a line, it means, that the - // initilal PointId is set. The next addition of a pointId adds - // a line - polygon->AddPointId(pId); - - // select the line, if we really added a line, so now have more than - // 1 pointID in the cell - CellDataType cellData; - ok = m_PointSetSeries[0]->GetCellData(cellId, &cellData); - if (ok) - { - // A line between point 0 and 1 has the Id 0. A line between - // 1 and 2 has a Id = 1. So we add getnumberofpoints-2. - if (polygon->GetNumberOfPoints() > 1) - cellData.selectedLines.push_back(polygon->GetNumberOfPoints() - 2); - } - m_PointSetSeries[0]->SetCellData(cellId, cellData); - m_PointSetSeries[0]->SetCell(cellId, cellAutoPointer); - } - } - } - break; - - case OpDELETELINE: - { - // deleted the last line through removing the index PIdA - // (if set to -1, use the last point) in the given cellId - auto *lineOp = dynamic_cast(operation); - int cellId = -1; - int pId = -1; - - if (lineOp == nullptr) - { - cellId = this->SearchSelectedCell(0); - if (cellId == -1) - return; - pId = this->SearchSelectedPoint(0); - } - else - { - cellId = lineOp->GetCellId(); - if (cellId == -1) - return; - pId = lineOp->GetPIdA(); - } - - bool ok; - CellAutoPointer cellAutoPointer; - ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); - if (ok) - { - CellType *cell = cellAutoPointer.GetPointer(); - if (cell->GetType() == CellType::POLYGON_CELL) - { - auto *oldPolygon = static_cast(cell); - - auto newPolygonCell = new PolygonType; - CellAutoPointer newCell; - newCell.TakeOwnership(newPolygonCell); - - PointIdConstIterator it, oldend; - oldend = oldPolygon->PointIdsEnd(); - if (pId >= 0) - { - for (it = oldPolygon->PointIdsBegin(); it != oldend; ++it) - { - if ((*it) != (MeshType::PointIdentifier)pId) - { - newPolygonCell->AddPointId(*it); - } - } - } - else - { - --oldend; - for (it = oldPolygon->PointIdsBegin(); it != oldend; ++it) - newPolygonCell->AddPointId(*it); - } - oldPolygon->SetPointIds(0, newPolygonCell->GetNumberOfPoints(), newPolygonCell->PointIdsBegin()); - } - } - } - break; - - case OpREMOVELINE: - // Remove the given Index in the given cell through copying everything - // into a new cell accept the one that has to be deleted. - { - auto *lineOp = dynamic_cast(operation); - if (lineOp == nullptr) // if no lineoperation, then call superclass pointSet - { - Superclass::ExecuteOperation(operation); - } - - bool ok; - CellAutoPointer cellAutoPointer; - int cellId = lineOp->GetCellId(); - ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); - if (!ok) - return; - - CellType *cell = cellAutoPointer.GetPointer(); - CellAutoPointer newCellAutoPointer; - newCellAutoPointer.TakeOwnership(new PolygonType); - auto *newPolygon = static_cast(cell); - - PointIdIterator it = cell->PointIdsBegin(); - PointIdIterator end = cell->PointIdsEnd(); - int pointId = lineOp->GetPIdA(); - if (pointId < 0) // if not initialized!! - return; - - while (it != end) - { - if ((*it) == (unsigned int)pointId) - { - break; - } - else - { - newPolygon->AddPointId(*it); - } - ++it; - } - while (it != end) - { - newPolygon->AddPointId(*it); - it++; - } - m_PointSetSeries[0]->SetCell(cellId, newCellAutoPointer); - } - break; - - case OpINSERTLINE: - // //insert line between two other points. - ////before A--B after A--C--B - // //the points A, B and C have to be in the pointset. - // //needed: CellId, Id of C , Id A and Id B - ////the cell has to exist! - //{ - // mitk::LineOperation *lineOp = dynamic_cast(operation); - // if (lineOp == nullptr)//if no lineoperation, then call superclass pointSet - // { - // Superclass::ExecuteOperation(operation); - // } - // int cellId = lineOp->GetCellId(); - // int pIdC = lineOp->GetPIdC(); - // int pIdA = lineOp->GetPIdA(); - // int pIdB = lineOp->GetPIdB(); - - // //the points of the given PointIds have to exist in the PointSet - // bool ok; - // ok = m_PointSetSeries[0]->GetPoints()->IndexExists(pIdA); - // if (!ok) - // return; - // ok = m_PointSetSeries[0]->GetPoints()->IndexExists(pIdB); - // if (!ok) - // return; - // ok = m_PointSetSeries[0]->GetPoints()->IndexExists(pIdC); - // if (!ok) - // return; - - // // so the points do exist. So now check, if there is already a cell - // // with the given Id - // DataType::CellAutoPointer cell; - // ok = m_PointSetSeries[0]->GetCell(cellId, cell); - // if (!ok) - // return; - - // //pIdA and pIdB should exist in the cell - // - // PointIdIterator pit = cell->PointIdsBegin(); - // PointIdIterator end = cell->PointIdsEnd(); - // - // //now arrange the new Ids in the cell like desired; pIdC between - // // pIdA and pIdB - // unsigned int nuPoints = cell->GetNumberOfPoints(); - - // std::vector newPoints; - // pit = cell->PointIdsBegin(); - // end = cell->PointIdsEnd(); - // int i = 0; - // while( pit != end ) - // { - // if ((*pit) = pIdA) - // { - // //now we have found the place to add pIdC after - // newPoints[i] = (*pit); - // i++; - // newPoints[i] = pIdC; - // } - // else - // newPoints[i] = (*pit); - // pit++; - // } - - // //now we have the Ids, that existed before combined with the new ones - // //so delete the old cell - // //doesn't seem to be necessary! - // //cell->ClearPoints(); - // pit = cell->PointIdsBegin(); - // cell->SetPointIds(pit); - //} - break; - - case OpMOVELINE: //(moves two points) - { - auto *lineOp = dynamic_cast(operation); - - if (lineOp == nullptr) - { - mitk::StatusBar::GetInstance()->DisplayText( - "Message from mitkMesh: Recieved wrong type of operation! See mitkMeshInteractor.cpp", 10000); - return; - } - - // create two operations out of the one operation and call superclass - // through the transmitted pointIds get the koordinates of the points. - // then add the transmitted vestor to them - // create two operations and send them to superclass - Point3D pointA, pointB; - pointA.Fill(0.0); - pointB.Fill(0.0); - m_PointSetSeries[0]->GetPoint(lineOp->GetPIdA(), &pointA); - m_PointSetSeries[0]->GetPoint(lineOp->GetPIdB(), &pointB); - - pointA[0] += lineOp->GetVector()[0]; - pointA[1] += lineOp->GetVector()[1]; - pointA[2] += lineOp->GetVector()[2]; - pointB[0] += lineOp->GetVector()[0]; - pointB[1] += lineOp->GetVector()[1]; - pointB[2] += lineOp->GetVector()[2]; - - auto operationA = new mitk::PointOperation(OpMOVE, pointA, lineOp->GetPIdA()); - auto operationB = new mitk::PointOperation(OpMOVE, pointB, lineOp->GetPIdB()); - - Superclass::ExecuteOperation(operationA); - Superclass::ExecuteOperation(operationB); - } - break; - - case OpSELECTLINE: //(select the given line) - { - auto *lineOp = dynamic_cast(operation); - if (lineOp == nullptr) // if no lineoperation, then call superclass pointSet - { - Superclass::ExecuteOperation(operation); - } - int cellId = lineOp->GetCellId(); - CellAutoPointer cellAutoPointer; - bool ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); - if (ok) - { - CellDataType cellData; - m_PointSetSeries[0]->GetCellData(cellId, &cellData); - SelectedLinesType *selectedLines = &(cellData.selectedLines); - auto position = std::find(selectedLines->begin(), selectedLines->end(), (unsigned int)lineOp->GetId()); - - if (position == selectedLines->end()) // if not alsready selected - { - cellData.selectedLines.push_back(lineOp->GetId()); - } - m_PointSetSeries[0]->SetCellData(lineOp->GetCellId(), cellData); - } - } - break; - - case OpDESELECTLINE: //(deselect the given line) - { - auto *lineOp = dynamic_cast(operation); - if (lineOp == nullptr) - { - Superclass::ExecuteOperation(operation); - } - int cellId = lineOp->GetCellId(); - CellAutoPointer cellAutoPointer; - bool ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); - if (ok) - { - CellDataType cellData; - m_PointSetSeries[0]->GetCellData(cellId, &cellData); - SelectedLinesType *selectedLines = &(cellData.selectedLines); - auto position = std::find(selectedLines->begin(), selectedLines->end(), (unsigned int)lineOp->GetId()); - - if (position != selectedLines->end()) // if found - { - selectedLines->erase(position); - } - m_PointSetSeries[0]->SetCellData(cellId, cellData); - } - } - break; - - case OpSELECTCELL: //(select the given cell) - { - auto *lineOp = dynamic_cast(operation); - if (lineOp == nullptr) // if no lineoperation, then call superclass pointSet - { - Superclass::ExecuteOperation(operation); - } - - int cellId = lineOp->GetCellId(); - CellAutoPointer cellAutoPointer; - - // directly get the data!//TODO - bool ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); - if (ok) - { - CellDataType cellData; - m_PointSetSeries[0]->GetCellData(cellId, &cellData); - cellData.selected = true; - m_PointSetSeries[0]->SetCellData(cellId, cellData); - } - } - break; - - case OpDESELECTCELL: //(deselect the given cell) - { - auto *lineOp = dynamic_cast(operation); - if (lineOp == nullptr) // if no lineoperation, then call superclass pointSet - { - Superclass::ExecuteOperation(operation); - } - int cellId = lineOp->GetCellId(); - CellAutoPointer cellAutoPointer; - bool ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); - if (ok) - { - CellDataType cellData; - m_PointSetSeries[0]->GetCellData(cellId, &cellData); - cellData.selected = false; - m_PointSetSeries[0]->SetCellData(cellId, cellData); - } - } - break; - - case OpMOVECELL: - // moves all Points of one cell according to the given vector - { - auto *lineOp = dynamic_cast(operation); - if (lineOp == nullptr) // if no celloperation, then call superclass pointSet - { - Superclass::ExecuteOperation(operation); - } - - int cellId = lineOp->GetCellId(); - Vector3D vector = lineOp->GetVector(); - - // get the cell - CellAutoPointer cellAutoPointer; - bool ok = m_PointSetSeries[0]->GetCell(cellId, cellAutoPointer); - if (!ok) - return; - - CellDataType cellData; - m_PointSetSeries[0]->GetCellData(cellId, &cellData); - // iterate through the pointIds of the CellData and move those points in - // the pointset - PointIdIterator it = cellAutoPointer->PointIdsBegin(); - PointIdIterator end = cellAutoPointer->PointIdsEnd(); - while (it != end) - { - unsigned int position = (*it); - PointType point; - point.Fill(0); - m_PointSetSeries[0]->GetPoint(position, &point); - point = point + vector; - m_PointSetSeries[0]->SetPoint(position, point); - ++it; - } - } - break; - - default: - // if the operation couldn't be handled here, then send it to superclass - Superclass::ExecuteOperation(operation); - return; - } - // to tell the mappers, that the data is modifierd and has to be updated - this->Modified(); - - mitk::OperationEndEvent endevent(operation); - ((const itk::Object *)this)->InvokeEvent(endevent); - - // As discussed lately, don't mess with rendering from inside data structures - //*todo has to be done here, cause of update-pipeline not working yet - // mitk::RenderingManager::GetInstance()->RequestUpdateAll(); -} - -mitk::Mesh::DataType::BoundingBoxPointer mitk::Mesh::GetBoundingBoxFromCell(unsigned long cellId, int t) -{ - // itk::CellInterface has also a GetBoundingBox, but it - // returns CoordRepType [PointDimension *2] - DataType::BoundingBoxPointer bBoxPointer = nullptr; - CellAutoPointer cellAutoPointer; - if (m_PointSetSeries[t]->GetCell(cellId, cellAutoPointer)) - { - DataType::PointsContainerPointer pointsContainer = DataType::PointsContainer::New(); - PointIdIterator bbIt = cellAutoPointer.GetPointer()->PointIdsBegin(); - PointIdIterator bbEnd = cellAutoPointer.GetPointer()->PointIdsEnd(); - while (bbIt != bbEnd) - { - mitk::PointSet::PointType point; - bool pointOk = m_PointSetSeries[t]->GetPoint((*bbIt), &point); - if (pointOk) - pointsContainer->SetElement((*bbIt), point); - ++bbIt; - } - bBoxPointer = DataType::BoundingBoxType::New(); - bBoxPointer->SetPoints(pointsContainer); - bBoxPointer->ComputeBoundingBox(); - } - return bBoxPointer; -} diff --git a/Modules/DataTypesExt/test/files.cmake b/Modules/DataTypesExt/test/files.cmake index 048ece655e..356091d282 100644 --- a/Modules/DataTypesExt/test/files.cmake +++ b/Modules/DataTypesExt/test/files.cmake @@ -1,18 +1,17 @@ set(MODULE_TESTS mitkColorSequenceRainbowTest.cpp - mitkMeshTest.cpp mitkMultiStepperTest.cpp mitkUnstructuredGridTest.cpp ) set(MODULE_IMAGE_TESTS mitkCompressedImageContainerTest.cpp #only runs on images ) set(MODULE_TESTIMAGE US4DCyl.nrrd Pic3D.nrrd Pic2DplusT.nrrd BallBinary30x30x30.nrrd Png2D-bw.png ) diff --git a/Modules/DataTypesExt/test/mitkMeshTest.cpp b/Modules/DataTypesExt/test/mitkMeshTest.cpp deleted file mode 100644 index aa6dd719a9..0000000000 --- a/Modules/DataTypesExt/test/mitkMeshTest.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#include -#include -#include -#include -#include - -int mitkMeshTest(int /*argc*/, char * /*argv*/ []) -{ - // Create mesh - mitk::Mesh::Pointer mesh; - mesh = mitk::Mesh::New(); - - // try to get the itkmesh - std::cout << "Create a mesh and try to get the itkMesh"; - mitk::Mesh::DataType::Pointer itkdata = nullptr; - itkdata = mesh->GetMesh(); - if (itkdata.IsNull()) - { - std::cout << "[FAILED]" << std::endl; - return EXIT_FAILURE; - } - - // fresh mesh has to be empty! - std::cout << "Is the mesh empty?"; - if (mesh->GetSize() != 0) - { - std::cout << "[FAILED]" << std::endl; - return EXIT_FAILURE; - } - - // create an operation and add a point. - int position = 0; - mitk::Point3D point; - point.Fill(1); - auto doOp = new mitk::PointOperation(mitk::OpINSERT, point, position); - mesh->ExecuteOperation(doOp); - - // now check new condition! - if ((mesh->GetSize() != 1) || (!mesh->IndexExists(position))) - { - std::cout << "[FAILED]" << std::endl; - return EXIT_FAILURE; - } - delete doOp; - - // get the point and check if it is still the same - std::cout << "Create an operation and add a point. Then try to get that point."; - mitk::Point3D tempPoint; - tempPoint.Fill(0); - tempPoint = mesh->GetPoint(position); - if (tempPoint != point) - { - std::cout << "[FAILED]" << std::endl; - return EXIT_FAILURE; - } - - // well done!!! Passed! - std::cout << "[PASSED]" << std::endl; - - std::cout << "[TEST DONE]" << std::endl; - return EXIT_SUCCESS; -} diff --git a/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp b/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp index d268917ff6..86ca564d52 100644 --- a/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp +++ b/Modules/IOExt/Internal/mitkIOExtObjectFactory.cpp @@ -1,180 +1,167 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "mitkIOExtObjectFactory.h" #include "mitkCoreObjectFactory.h" #include "mitkParRecFileIOFactory.h" //#include "mitkObjFileIOFactory.h" #include "mitkStlVolumeTimeSeriesIOFactory.h" #include "mitkVtkVolumeTimeSeriesIOFactory.h" #include "mitkUnstructuredGridVtkWriter.h" #include "mitkUnstructuredGridVtkWriterFactory.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)) + 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) && std::string("Image").compare(node->GetData()->GetNameOfClass())==0) { 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::VolumeMapperVtkSmart3D::SetDefaultProperties(node); } if (dynamic_cast(node->GetData())) { mitk::UnstructuredGridVtkMapper3D::SetDefaultProperties(node); } } std::string 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")); } std::string 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/ImageStatistics/mitkExtendedLabelStatisticsImageFilter.hxx b/Modules/ImageStatistics/mitkExtendedLabelStatisticsImageFilter.hxx index 794133be0a..05223f2105 100644 --- a/Modules/ImageStatistics/mitkExtendedLabelStatisticsImageFilter.hxx +++ b/Modules/ImageStatistics/mitkExtendedLabelStatisticsImageFilter.hxx @@ -1,756 +1,737 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef _mitkExtendedLabelStatisticsImageFilter_hxx #define _mitkExtendedLabelStatisticsImageFilter_hxx #include "mitkExtendedLabelStatisticsImageFilter.h" #include "itkImageRegionConstIteratorWithIndex.h" #include "itkImageRegionConstIterator.h" #include #include #include "mitkNumericConstants.h" #include "mitkLogMacros.h" #include namespace itk { template< class TInputImage, class TLabelImage > bool ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetMaskingNonEmpty() const { return m_MaskNonEmpty; } template< typename TInputImage, typename TLabelImage > void ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::SetHistogramParameters(const int numBins, RealType lowerBound, RealType upperBound) { m_NumBins[0] = numBins; m_LowerBound = lowerBound; m_UpperBound = upperBound; m_GlobalHistogramParametersSet = true; m_PreferGlobalHistogramParameters = true; this->Modified(); } template< typename TInputImage, typename TLabelImage > void ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::SetHistogramParametersForLabels(std::map numBins, std::map lowerBound, std::map upperBound) { m_LabelMin = lowerBound; m_LabelMax = upperBound; m_LabelNBins = numBins; m_LabelHistogramParametersSet = true; m_PreferGlobalHistogramParameters = false; this->Modified(); } template< class TInputImage, class TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetUniformity(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::Zero; + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Uniformity; } } template< class TInputImage, class TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetMedian(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::Zero; + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Median; } } template< class TInputImage, class TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetEntropy(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::Zero; + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Entropy; } } template< class TInputImage, class TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetUPP(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::Zero; + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_UPP; } } template< class TInputImage, class TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetMPP(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::Zero; + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_MPP; } } template< class TInputImage, class TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetKurtosis(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::Zero; + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Kurtosis; } } template< class TInputImage, class TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetSkewness(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::Zero; + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Skewness; } } template< typename TInputImage, typename TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetMinimum(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::max(); + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Minimum; } } template< typename TInputImage, typename TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetMaximum(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::NonpositiveMin(); + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Maximum; } } template< typename TInputImage, typename TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetMean(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::ZeroValue(); + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Mean; } } template< typename TInputImage, typename TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetSum(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::ZeroValue(); + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Sum; } } template< typename TInputImage, typename TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetSigma(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::ZeroValue(); + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Sigma; } } template< typename TInputImage, typename TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RealType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetVariance(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return NumericTraits< PixelType >::ZeroValue(); + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Variance; } } template< typename TInputImage, typename TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::BoundingBoxType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetBoundingBox(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - typename Superclass::BoundingBoxType emptyBox; - // label does not exist, return a default value - return emptyBox; + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_BoundingBox; } } template< typename TInputImage, typename TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::RegionType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetRegion(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - typename Superclass::RegionType emptyRegion; - // label does not exist, return a default value - return emptyRegion; + mitkThrow() << "Label does not exist"; } else { typename Superclass::BoundingBoxType bbox = this->GetBoundingBox(label); typename Superclass::IndexType index; typename Superclass::SizeType size; unsigned int dimension = bbox.size() / 2; for ( unsigned int i = 0; i < dimension; i++ ) { index[i] = bbox[2 * i]; size[i] = bbox[2 * i + 1] - bbox[2 * i] + 1; } typename Superclass::RegionType region; region.SetSize(size); region.SetIndex(index); return region; } } template< typename TInputImage, typename TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::MapSizeType ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetCount(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return 0; + mitkThrow() << "Label does not exist"; } else { return ( *mapIt ).second.m_Count; } } template< typename TInputImage, typename TLabelImage > typename ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >::HistogramType::Pointer ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetHistogram(LabelPixelType label) const { StatisticsMapConstIterator mapIt; mapIt = m_LabelStatistics.find(label); if ( mapIt == m_LabelStatistics.end() ) { - // label does not exist, return a default value - return ITK_NULLPTR; + mitkThrow() << "Label does not exist"; } else { // this will be zero if histograms have not been enabled return ( *mapIt ).second.m_Histogram; } } template< typename TInputImage, typename TLabelImage > void ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::BeforeThreadedGenerateData() { ThreadIdType numberOfThreads = this->GetNumberOfThreads(); // Resize the thread temporaries m_LabelStatisticsPerThread.resize(numberOfThreads); // Initialize the temporaries for ( ThreadIdType i = 0; i < numberOfThreads; ++i ) { m_LabelStatisticsPerThread[i].clear(); } // Initialize the final map m_LabelStatistics.clear(); } template< typename TInputImage, typename TLabelImage > std::list ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::GetRelevantLabels() const { std::list< int> relevantLabels; for (int i = 0; i < 4096; ++i ) { if ( this->HasLabel( i ) ) { relevantLabels.push_back( i ); } } return relevantLabels; } template< typename TInputImage, typename TLabelImage > void ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage > ::ThreadedGenerateData(const typename TInputImage::RegionType & outputRegionForThread, ThreadIdType threadId) { typename HistogramType::IndexType histogramIndex(1); typename HistogramType::MeasurementVectorType histogramMeasurement(1); const SizeValueType size0 = outputRegionForThread.GetSize(0); if( size0 == 0) { return; } ImageLinearConstIteratorWithIndex< TInputImage > it (this->GetInput(), outputRegionForThread); ImageScanlineConstIterator< TLabelImage > labelIt (this->GetLabelInput(), outputRegionForThread); StatisticsMapIterator mapIt; // support progress methods/callbacks const size_t numberOfLinesToProcess = outputRegionForThread.GetNumberOfPixels() / size0; ProgressReporter progress( this, threadId, numberOfLinesToProcess ); typedef typename MapType::value_type MapValueType; // do the work while ( !it.IsAtEnd() ) { while ( !it.IsAtEndOfLine() ) { const RealType & value = static_cast< RealType >( it.Get() ); const LabelPixelType & label = labelIt.Get(); // is the label already in this thread? mapIt = m_LabelStatisticsPerThread[threadId].find(label); if ( mapIt == m_LabelStatisticsPerThread[threadId].end() ) { // if global histogram parameters are set and preferred then use them if ( m_PreferGlobalHistogramParameters && m_GlobalHistogramParametersSet ) { mapIt = m_LabelStatisticsPerThread[threadId].insert( MapValueType( label, LabelStatistics(m_NumBins[0], m_LowerBound, m_UpperBound) ) ).first; } // if we have label histogram parameters then use them. If we encounter a label that has no parameters then use global settings if available else if(!m_PreferGlobalHistogramParameters && m_LabelHistogramParametersSet) { typename std::map::iterator lbIt, ubIt; typename std::map::iterator nbIt; lbIt = m_LabelMin.find(label); ubIt = m_LabelMax.find(label); nbIt = m_LabelNBins.find(label); // if any of the parameters is lacking for the current label but global histogram params are available, use the global parameters if ((lbIt == m_LabelMin.end() || ubIt == m_LabelMax.end() || nbIt == m_LabelNBins.end()) && m_GlobalHistogramParametersSet) { mapIt = m_LabelStatisticsPerThread[threadId].insert( MapValueType( label, LabelStatistics(m_NumBins[0], m_LowerBound, m_UpperBound) ) ).first; } // if any of the parameters is lacking for the current label and global histogram params are not available, dont use histograms for this label else if ((lbIt == m_LabelMin.end() || ubIt == m_LabelMax.end() || nbIt == m_LabelNBins.end()) && !m_GlobalHistogramParametersSet) { mapIt = m_LabelStatisticsPerThread[threadId].insert( MapValueType( label, LabelStatistics() ) ).first; } // label histogram parameters are available, use them! else { PixelType lowerBound, upperBound; unsigned int nBins; lowerBound = (*lbIt).second; upperBound = (*ubIt).second; nBins = (*nbIt).second; mapIt = m_LabelStatisticsPerThread[threadId].insert( MapValueType( label, LabelStatistics(nBins, lowerBound, upperBound) ) ).first; } } // neither global nor label specific histogram parameters are set -> don't use histograms else { mapIt = m_LabelStatisticsPerThread[threadId].insert( MapValueType( label, LabelStatistics() ) ).first; } } typename MapType::mapped_type &labelStats = ( *mapIt ).second; // update the values for this label and this thread if ( value < labelStats.m_Minimum ) { labelStats.m_Minimum = value; } if ( value > labelStats.m_Maximum ) { labelStats.m_Maximum = value; } // bounding box is min,max pairs for ( unsigned int i = 0; i < ( 2 * TInputImage::ImageDimension ); i += 2 ) { const typename TInputImage::IndexType & index = it.GetIndex(); if ( labelStats.m_BoundingBox[i] > index[i / 2] ) { labelStats.m_BoundingBox[i] = index[i / 2]; } if ( labelStats.m_BoundingBox[i + 1] < index[i / 2] ) { labelStats.m_BoundingBox[i + 1] = index[i / 2]; } } labelStats.m_Sum += value; labelStats.m_SumOfSquares += ( value * value ); labelStats.m_Count++; labelStats.m_SumOfCubes += std::pow(value, 3.); labelStats.m_SumOfQuadruples += std::pow(value, 4.); if (value > 0) { labelStats.m_PositivePixelCount++; labelStats.m_SumOfPositivePixels += value; } // if enabled, update the histogram for this label if ( labelStats.m_Histogram.IsNotNull() ) { histogramMeasurement[0] = value; labelStats.m_Histogram->GetIndex(histogramMeasurement, histogramIndex); labelStats.m_Histogram->IncreaseFrequencyOfIndex(histogramIndex, 1); } ++labelIt; ++it; } labelIt.NextLine(); it.NextLine(); progress.CompletedPixel(); } } template< class TInputImage, class TLabelImage > void ExtendedLabelStatisticsImageFilter< TInputImage, TLabelImage >:: AfterThreadedGenerateData() { StatisticsMapIterator mapIt; StatisticsMapConstIterator threadIt; ThreadIdType i; ThreadIdType numberOfThreads = this->GetNumberOfThreads(); // Run through the map for each thread and accumulate the count, // sum, and sumofsquares for ( i = 0; i < numberOfThreads; i++ ) { // iterate over the map for this thread for ( threadIt = m_LabelStatisticsPerThread[i].begin(); threadIt != m_LabelStatisticsPerThread[i].end(); ++threadIt ) { // does this label exist in the cumulative structure yet? mapIt = m_LabelStatistics.find( ( *threadIt ).first ); if ( mapIt == m_LabelStatistics.end() ) { // create a new entry typedef typename MapType::value_type MapValueType; if ( m_GlobalHistogramParametersSet || m_LabelHistogramParametersSet ) { // mapIt = m_LabelStatistics.insert( MapValueType( ( *threadIt ).first, // LabelStatistics(m_NumBins[0], m_LowerBound, // m_UpperBound) ) ).first; mapIt = m_LabelStatistics.insert( MapValueType( *threadIt ) ).first; continue; } else { mapIt = m_LabelStatistics.insert( MapValueType( ( *threadIt ).first, LabelStatistics() ) ).first; } } typename MapType::mapped_type &labelStats = ( *mapIt ).second; // accumulate the information from this thread labelStats.m_Count += ( *threadIt ).second.m_Count; labelStats.m_Sum += ( *threadIt ).second.m_Sum; labelStats.m_SumOfSquares += ( *threadIt ).second.m_SumOfSquares; labelStats.m_SumOfPositivePixels += ( *threadIt ).second.m_SumOfPositivePixels; labelStats.m_PositivePixelCount += ( *threadIt ).second.m_PositivePixelCount; labelStats.m_SumOfCubes += ( *threadIt ).second.m_SumOfCubes; labelStats.m_SumOfQuadruples += ( *threadIt ).second.m_SumOfQuadruples; if ( labelStats.m_Minimum > ( *threadIt ).second.m_Minimum ) { labelStats.m_Minimum = ( *threadIt ).second.m_Minimum; } if ( labelStats.m_Maximum < ( *threadIt ).second.m_Maximum ) { labelStats.m_Maximum = ( *threadIt ).second.m_Maximum; } //bounding box is min,max pairs int dimension = labelStats.m_BoundingBox.size() / 2; for ( int ii = 0; ii < ( dimension * 2 ); ii += 2 ) { if ( labelStats.m_BoundingBox[ii] > ( *threadIt ).second.m_BoundingBox[ii] ) { labelStats.m_BoundingBox[ii] = ( *threadIt ).second.m_BoundingBox[ii]; } if ( labelStats.m_BoundingBox[ii + 1] < ( *threadIt ).second.m_BoundingBox[ii + 1] ) { labelStats.m_BoundingBox[ii + 1] = ( *threadIt ).second.m_BoundingBox[ii + 1]; } } // if enabled, update the histogram for this label if ( m_GlobalHistogramParametersSet || m_LabelHistogramParametersSet ) { typename HistogramType::IndexType index; index.SetSize(1); for ( unsigned int bin = 0; bin < labelStats.m_Histogram->Size(); bin++ ) { index[0] = bin; labelStats.m_Histogram->IncreaseFrequency( bin, ( *threadIt ).second.m_Histogram->GetFrequency(bin) ); } } } // end of thread map iterator loop } // end of thread loop // compute the remainder of the statistics for ( mapIt = m_LabelStatistics.begin(); mapIt != m_LabelStatistics.end(); ++mapIt ) { typename MapType::mapped_type &labelStats = ( *mapIt ).second; // mean labelStats.m_Mean = labelStats.m_Sum / static_cast< RealType >( labelStats.m_Count ); // MPP labelStats.m_MPP = labelStats.m_SumOfPositivePixels / static_cast< RealType >( labelStats.m_PositivePixelCount ); // variance if ( labelStats.m_Count > 0 ) { // unbiased estimate of variance LabelStatistics & ls = mapIt->second; const RealType sumSquared = ls.m_Sum * ls.m_Sum; const RealType count = static_cast< RealType >( ls.m_Count ); ls.m_Variance = ( ls.m_SumOfSquares - sumSquared / count ) / ( count ); RealType secondMoment = ls.m_SumOfSquares / count; RealType thirdMoment = ls.m_SumOfCubes / count; RealType fourthMoment = ls.m_SumOfQuadruples / count; ls.m_Skewness = (thirdMoment - 3. * secondMoment * ls.m_Mean + 2. * std::pow(ls.m_Mean, 3.)) / std::pow(secondMoment - std::pow(ls.m_Mean, 2.), 1.5); // see http://www.boost.org/doc/libs/1_51_0/doc/html/boost/accumulators/impl/skewness_impl.html ls.m_Kurtosis = (fourthMoment - 4. * thirdMoment * ls.m_Mean + 6. * secondMoment * std::pow(ls.m_Mean, 2.) - 3. * std::pow(ls.m_Mean, 4.)) / std::pow(secondMoment - std::pow(ls.m_Mean, 2.), 2.); // see http://www.boost.org/doc/libs/1_51_0/doc/html/boost/accumulators/impl/kurtosis_impl.html, dropped -3 } else { labelStats.m_Variance = NumericTraits< RealType >::ZeroValue(); labelStats.m_Skewness = NumericTraits< RealType >::ZeroValue(); labelStats.m_Kurtosis = NumericTraits< RealType >::ZeroValue(); } // sigma labelStats.m_Sigma = std::sqrt( labelStats.m_Variance ); // histogram statistics if (labelStats.m_Histogram.IsNotNull()) { mitk::HistogramStatisticsCalculator histStatCalc; histStatCalc.SetHistogram(labelStats.m_Histogram); histStatCalc.CalculateStatistics(); labelStats.m_Median = histStatCalc.GetMedian(); labelStats.m_Entropy = histStatCalc.GetEntropy(); labelStats.m_Uniformity = histStatCalc.GetUniformity(); labelStats.m_UPP = histStatCalc.GetUPP(); } } { //Now update the cached vector of valid labels. m_ValidLabelValues.resize(0); m_ValidLabelValues.reserve(m_LabelStatistics.size()); for ( mapIt = m_LabelStatistics.begin(); mapIt != m_LabelStatistics.end(); ++mapIt ) { m_ValidLabelValues.push_back(mapIt->first); } } } } // end namespace itk #endif diff --git a/Modules/MapperExt/files.cmake b/Modules/MapperExt/files.cmake index 3ec5ef80f6..01778f6a7a 100644 --- a/Modules/MapperExt/files.cmake +++ b/Modules/MapperExt/files.cmake @@ -1,20 +1,18 @@ 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 vtkUnstructuredGridMapper.cpp vtkPointSetSlicer.cxx ) diff --git a/Modules/MapperExt/include/mitkMeshMapper2D.h b/Modules/MapperExt/include/mitkMeshMapper2D.h deleted file mode 100644 index 30926d3089..0000000000 --- a/Modules/MapperExt/include/mitkMeshMapper2D.h +++ /dev/null @@ -1,53 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#ifndef MITKMESHMAPPER2D_H_HEADER_INCLUDED -#define MITKMESHMAPPER2D_H_HEADER_INCLUDED - -#include "MitkMapperExtExports.h" -#include "mitkCommon.h" -#include "mitkGLMapper.h" - -namespace mitk -{ - class BaseRenderer; - class Mesh; - - /** - * \brief OpenGL-based mapper to display a mesh in a 2D window - * - * \todo implement for AbstractTransformGeometry. - * \ingroup Mapper - */ - class MITKMAPPEREXT_EXPORT MeshMapper2D : public GLMapper - { - public: - mitkClassMacro(MeshMapper2D, GLMapper); - - itkFactorylessNewMacro(Self); - - itkCloneMacro(Self); - - /** @brief Get the Mesh to map */ - const mitk::Mesh *GetInput(void); - - void Paint(mitk::BaseRenderer *renderer) override; - - protected: - MeshMapper2D(); - - ~MeshMapper2D() override; - }; - -} // namespace mitk - -#endif /* MITKMESHMapper2D_H_HEADER_INCLUDED */ diff --git a/Modules/MapperExt/include/mitkMeshVtkMapper3D.h b/Modules/MapperExt/include/mitkMeshVtkMapper3D.h deleted file mode 100644 index 59391e03f4..0000000000 --- a/Modules/MapperExt/include/mitkMeshVtkMapper3D.h +++ /dev/null @@ -1,87 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#ifndef MITKMESHVTKMAPPER3D_H_HEADER_INCLUDED -#define MITKMESHVTKMAPPER3D_H_HEADER_INCLUDED - -#include "MitkMapperExtExports.h" -#include "mitkBaseRenderer.h" -#include "mitkCommon.h" -#include "mitkMesh.h" -#include "mitkVtkMapper.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class vtkActor; -class vtkAssembly; -class vtkFollower; -class vtkPolyDataMapper; -class vtkPropAssembly; - -namespace mitk -{ - /** - * \brief Vtk-based mapper for PointList - * \ingroup Mapper - */ - class MITKMAPPEREXT_EXPORT MeshVtkMapper3D : public VtkMapper - { - public: - mitkClassMacro(MeshVtkMapper3D, VtkMapper); - - itkFactorylessNewMacro(Self); - - itkCloneMacro(Self); - - virtual const mitk::Mesh *GetInput(); - - vtkProp *GetVtkProp(mitk::BaseRenderer *renderer) override; - void UpdateVtkTransform(mitk::BaseRenderer *renderer) override; - - LocalStorageHandler m_LSH; - - protected: - MeshVtkMapper3D(); - - ~MeshVtkMapper3D() override; - - void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override; - - void ResetMapper(BaseRenderer *renderer) override; - - vtkPropAssembly *m_PropAssembly; - - vtkActor *m_SpheresActor; - vtkActor *m_ContourActor; - vtkPolyDataMapper *m_ContourMapper; - vtkPolyDataMapper *m_SpheresMapper; - - vtkPolyDataMapper *m_TextVtkPolyDataMapper; - - vtkAppendPolyData *m_Spheres; - vtkPolyData *m_Contour; - }; - -} // namespace mitk - -#endif /* MITKMESHVTKMAPPER3D_H_HEADER_INCLUDED*/ diff --git a/Modules/MapperExt/src/mitkMeshMapper2D.cpp b/Modules/MapperExt/src/mitkMeshMapper2D.cpp deleted file mode 100644 index c67bb42de6..0000000000 --- a/Modules/MapperExt/src/mitkMeshMapper2D.cpp +++ /dev/null @@ -1,472 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#include "mitkMeshMapper2D.h" -#include "mitkBaseRenderer.h" -#include "mitkColorProperty.h" -#include "mitkGL.h" -#include "mitkLine.h" -#include "mitkMesh.h" -#include "mitkPlaneGeometry.h" -#include "mitkProperties.h" - -#include - -#include - -const float selectedColor[] = {1.0f, 0.0f, 0.6f}; // for selected! - -mitk::MeshMapper2D::MeshMapper2D() -{ -} - -mitk::MeshMapper2D::~MeshMapper2D() -{ -} - -const mitk::Mesh *mitk::MeshMapper2D::GetInput(void) -{ - return static_cast(GetDataNode()->GetData()); -} - -// Return whether a point is "smaller" than the second -static bool point3DSmaller(const mitk::Point3D &elem1, const mitk::Point3D &elem2) -{ - if (elem1[0] != elem2[0]) - return elem1[0] < elem2[0]; - if (elem1[1] != elem2[1]) - return elem1[1] < elem2[1]; - return elem1[2] < elem2[2]; -} - -void mitk::MeshMapper2D::Paint(mitk::BaseRenderer *renderer) -{ - bool visible = true; - - GetDataNode()->GetVisibility(visible, renderer, "visible"); - - if (!visible) - return; - - // @FIXME: Logik fuer update - bool updateNeccesary = true; - - if (updateNeccesary) - { - // aus GenerateData - mitk::Mesh::Pointer input = const_cast(this->GetInput()); - - // Get the TimeGeometry of the input object - const TimeGeometry *inputTimeGeometry = input->GetTimeGeometry(); - if ((inputTimeGeometry == nullptr) || (inputTimeGeometry->CountTimeSteps() == 0)) - { - return; - } - - // - // get the world time - // - ScalarType time = renderer->GetTime(); - - // - // convert the world time in time steps of the input object - // - int timeStep = 0; - if (time > itk::NumericTraits::NonpositiveMin()) - timeStep = inputTimeGeometry->TimePointToTimeStep(time); - if (inputTimeGeometry->IsValidTimeStep(timeStep) == false) - { - return; - } - - mitk::Mesh::MeshType::Pointer itkMesh = input->GetMesh(timeStep); - - if (itkMesh.GetPointer() == nullptr) - { - return; - } - - const PlaneGeometry *worldplanegeometry = (renderer->GetCurrentWorldPlaneGeometry()); - - // apply color and opacity read from the PropertyList - ApplyColorAndOpacityProperties(renderer); - - vtkLinearTransform *transform = GetDataNode()->GetVtkTransform(); - - // List of the Points - Mesh::DataType::PointsContainerConstIterator it, end; - it = itkMesh->GetPoints()->Begin(); - end = itkMesh->GetPoints()->End(); - - // iterator on the additional data of each point - Mesh::PointDataIterator dataIt; //, dataEnd; - dataIt = itkMesh->GetPointData()->Begin(); - - // for switching back to old color after using selected color - float unselectedColor[4]; - glGetFloatv(GL_CURRENT_COLOR, unselectedColor); - - while (it != end) - { - mitk::Point3D p, projected_p; - float vtkp[3]; - - itk2vtk(it->Value(), vtkp); - transform->TransformPoint(vtkp, vtkp); - vtk2itk(vtkp, p); - - renderer->GetCurrentWorldPlaneGeometry()->Project(p, projected_p); - Vector3D diff = p - projected_p; - if (diff.GetSquaredNorm() < 4.0) - { - Point2D pt2d, tmp; - renderer->WorldToDisplay(p, pt2d); - - Vector2D horz, vert; - horz[0] = 5; - horz[1] = 0; - vert[0] = 0; - vert[1] = 5; - - // check if the point is to be marked as selected - if (dataIt->Value().selected) - { - horz[0] = 8; - vert[1] = 8; - glColor3f(selectedColor[0], selectedColor[1], selectedColor[2]); // red - - switch (dataIt->Value().pointSpec) - { - case PTSTART: - // a quad - glBegin(GL_LINE_LOOP); - tmp = pt2d - horz + vert; - glVertex2dv(&tmp[0]); - tmp = pt2d + horz + vert; - glVertex2dv(&tmp[0]); - tmp = pt2d + horz - vert; - glVertex2dv(&tmp[0]); - tmp = pt2d - horz - vert; - glVertex2dv(&tmp[0]); - glEnd(); - break; - case PTUNDEFINED: - // a diamond around the point - glBegin(GL_LINE_LOOP); - tmp = pt2d - horz; - glVertex2dv(&tmp[0]); - tmp = pt2d + vert; - glVertex2dv(&tmp[0]); - tmp = pt2d + horz; - glVertex2dv(&tmp[0]); - tmp = pt2d - vert; - glVertex2dv(&tmp[0]); - glEnd(); - break; - default: - break; - } // switch - - // the actual point - glBegin(GL_POINTS); - tmp = pt2d; - glVertex2dv(&tmp[0]); - glEnd(); - } - else // if not selected - { - glColor3f(unselectedColor[0], unselectedColor[1], unselectedColor[2]); - switch (dataIt->Value().pointSpec) - { - case PTSTART: - // a quad - glBegin(GL_LINE_LOOP); - tmp = pt2d - horz + vert; - glVertex2dv(&tmp[0]); - tmp = pt2d + horz + vert; - glVertex2dv(&tmp[0]); - tmp = pt2d + horz - vert; - glVertex2dv(&tmp[0]); - tmp = pt2d - horz - vert; - glVertex2dv(&tmp[0]); - glEnd(); - break; - case PTUNDEFINED: - // drawing crosses - glBegin(GL_LINES); - tmp = pt2d - horz; - glVertex2dv(&tmp[0]); - tmp = pt2d + horz; - glVertex2dv(&tmp[0]); - tmp = pt2d - vert; - glVertex2dv(&tmp[0]); - tmp = pt2d + vert; - glVertex2dv(&tmp[0]); - glEnd(); - break; - default: - { - break; - } - } // switch - } // else - } - ++it; - ++dataIt; - } - - // now connect the lines inbetween - mitk::Mesh::PointType thisPoint; - thisPoint.Fill(0); - Point2D *firstOfCell = nullptr; - Point2D *lastPoint = nullptr; - unsigned int lastPointId = 0; - bool lineSelected = false; - - Point3D firstOfCell3D; - Point3D lastPoint3D; - bool first; - mitk::Line line; - std::vector intersectionPoints; - double t; - - // iterate through all cells and then iterate through all indexes of points in that cell - Mesh::CellIterator cellIt, cellEnd; - Mesh::CellDataIterator cellDataIt; //, cellDataEnd; - Mesh::PointIdIterator cellIdIt, cellIdEnd; - - cellIt = itkMesh->GetCells()->Begin(); - cellEnd = itkMesh->GetCells()->End(); - cellDataIt = itkMesh->GetCellData()->Begin(); - - while (cellIt != cellEnd) - { - unsigned int numOfPointsInCell = cellIt->Value()->GetNumberOfPoints(); - if (numOfPointsInCell > 1) - { - // iterate through all id's in the cell - cellIdIt = cellIt->Value()->PointIdsBegin(); - cellIdEnd = cellIt->Value()->PointIdsEnd(); - - firstOfCell3D = input->GetPoint(*cellIdIt, timeStep); - - intersectionPoints.clear(); - intersectionPoints.reserve(numOfPointsInCell); - - first = true; - - while (cellIdIt != cellIdEnd) - { - lastPoint3D = thisPoint; - - thisPoint = input->GetPoint(*cellIdIt, timeStep); - - // search in data (vector<> selectedLines) if the index of the point is set. if so, then the line is selected. - lineSelected = false; - Mesh::SelectedLinesType selectedLines = cellDataIt->Value().selectedLines; - - // a line between 1(lastPoint) and 2(pt2d) has the Id 1, so look for the Id of lastPoint - // since we only start, if we have more than one point in the cell, lastPointId is initiated with 0 - auto position = std::find(selectedLines.begin(), selectedLines.end(), lastPointId); - if (position != selectedLines.end()) - { - lineSelected = true; - } - - mitk::Point3D p, projected_p; - float vtkp[3]; - itk2vtk(thisPoint, vtkp); - transform->TransformPoint(vtkp, vtkp); - vtk2itk(vtkp, p); - renderer->GetCurrentWorldPlaneGeometry()->Project(p, projected_p); - Vector3D diff = p - projected_p; - if (diff.GetSquaredNorm() < 4.0) - { - Point2D pt2d, tmp; - renderer->WorldToDisplay(p, pt2d); - - if (lastPoint == nullptr) - { - // set the first point in the cell. This point in needed to close the polygon - firstOfCell = new Point2D; - *firstOfCell = pt2d; - lastPoint = new Point2D; - *lastPoint = pt2d; - lastPointId = *cellIdIt; - } - else - { - if (lineSelected) - { - glColor3f(selectedColor[0], selectedColor[1], selectedColor[2]); // red - // a line from lastPoint to thisPoint - glBegin(GL_LINES); - glVertex2dv(&(*lastPoint)[0]); - glVertex2dv(&pt2d[0]); - glEnd(); - } - else // if not selected - { - glColor3f(unselectedColor[0], unselectedColor[1], unselectedColor[2]); - // drawing crosses - glBegin(GL_LINES); - glVertex2dv(&(*lastPoint)[0]); - glVertex2dv(&pt2d[0]); - glEnd(); - } - // to draw the line to the next in iteration step - *lastPoint = pt2d; - // and to search for the selection state of the line - lastPointId = *cellIdIt; - } // if..else - } // if <4.0 - - // fill off-plane polygon part 1 - if ((!first) && (worldplanegeometry != nullptr)) - { - line.SetPoints(lastPoint3D, thisPoint); - if (worldplanegeometry->IntersectionPointParam(line, t) && ((t >= 0) && (t <= 1))) - { - intersectionPoints.push_back(line.GetPoint(t)); - } - } - ++cellIdIt; - first = false; - } // while cellIdIter - - // closed polygon? - if (cellDataIt->Value().closed) - { - // close the polygon if needed - if (firstOfCell != nullptr) - { - lineSelected = false; - Mesh::SelectedLinesType selectedLines = cellDataIt->Value().selectedLines; - auto position = std::find(selectedLines.begin(), selectedLines.end(), lastPointId); - if (position != selectedLines.end()) // found the index - { - glColor3f(selectedColor[0], selectedColor[1], selectedColor[2]); // red - // a line from lastPoint to firstPoint - glBegin(GL_LINES); - glVertex2dv(&(*lastPoint)[0]); - glVertex2dv(&(*firstOfCell)[0]); - glEnd(); - } - else - { - glColor3f(unselectedColor[0], unselectedColor[1], unselectedColor[2]); - glBegin(GL_LINES); - glVertex2dv(&(*lastPoint)[0]); - glVertex2dv(&(*firstOfCell)[0]); - glEnd(); - } - } - } // if closed - - // Axis-aligned bounding box(AABB) around the cell if selected and set in Property - bool showBoundingBox; - if (dynamic_cast(this->GetDataNode()->GetProperty("showBoundingBox")) == nullptr) - showBoundingBox = false; - else - showBoundingBox = - dynamic_cast(this->GetDataNode()->GetProperty("showBoundingBox"))->GetValue(); - - if (showBoundingBox) - { - if (cellDataIt->Value().selected) - { - mitk::Mesh::DataType::BoundingBoxPointer aABB = input->GetBoundingBoxFromCell(cellIt->Index()); - if (aABB.IsNotNull()) - { - mitk::Mesh::PointType min, max; - min = aABB->GetMinimum(); - max = aABB->GetMaximum(); - - // project to the displayed geometry - Point2D min2D, max2D; - Point3D p, projected_p; - float vtkp[3]; - itk2vtk(min, vtkp); - transform->TransformPoint(vtkp, vtkp); - vtk2itk(vtkp, p); - renderer->WorldToDisplay(p, min2D); - - itk2vtk(max, vtkp); - transform->TransformPoint(vtkp, vtkp); - vtk2itk(vtkp, p); - renderer->GetCurrentWorldPlaneGeometry()->Project(p, projected_p); - Vector3D diff = p - projected_p; - if (diff.GetSquaredNorm() < 4.0) - { - renderer->WorldToDisplay(p, max2D); - - // draw the BoundingBox - glColor3f(selectedColor[0], selectedColor[1], selectedColor[2]); // red - // a line from lastPoint to firstPoint - glBegin(GL_LINE_LOOP); - glVertex2f(min2D[0], min2D[1]); - glVertex2f(min2D[0], max2D[1]); - glVertex2f(max2D[0], max2D[1]); - glVertex2f(max2D[0], min2D[1]); - glEnd(); - } // draw bounding-box - } // bounding-box exists - } // cell selected - } // show bounding-box - - // fill off-plane polygon part 2 - if (worldplanegeometry != nullptr) - { - // consider line from last to first - line.SetPoints(thisPoint, firstOfCell3D); - if (worldplanegeometry->IntersectionPointParam(line, t) && ((t >= 0) && (t <= 1))) - { - intersectionPoints.push_back(line.GetPoint(t)); - } - std::sort(intersectionPoints.begin(), intersectionPoints.end(), point3DSmaller); - std::vector::iterator it, end; - end = intersectionPoints.end(); - if ((intersectionPoints.size() % 2) != 0) - { - --end; // ensure even number of intersection-points - } - Point2D pt2d; - for (it = intersectionPoints.begin(); it != end; ++it) - { - glBegin(GL_LINES); - renderer->WorldToDisplay(*it, pt2d); - glVertex2dv(pt2d.GetDataPointer()); - ++it; - renderer->WorldToDisplay(*it, pt2d); - glVertex2dv(pt2d.GetDataPointer()); - glEnd(); - } - if (it != intersectionPoints.end()) - { - glBegin(GL_LINES); - renderer->WorldToDisplay(*it, pt2d); - glVertex2dv(pt2d.GetDataPointer()); - glVertex2dv(pt2d.GetDataPointer()); - glEnd(); - } - } // fill off-plane polygon part 2 - } // if numOfPointsInCell>1 - delete firstOfCell; - delete lastPoint; - lastPoint = nullptr; - firstOfCell = nullptr; - lastPointId = 0; - ++cellIt; - ++cellDataIt; - } - } -} diff --git a/Modules/MapperExt/src/mitkMeshVtkMapper3D.cpp b/Modules/MapperExt/src/mitkMeshVtkMapper3D.cpp deleted file mode 100644 index 1fca78d220..0000000000 --- a/Modules/MapperExt/src/mitkMeshVtkMapper3D.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#include "mitkMeshVtkMapper3D.h" -#include "mitkDataNode.h" -#include "mitkProperties.h" -#include "mitkVtkPropRenderer.h" - -#ifndef VCL_VC60 -#include "mitkMeshUtil.h" -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -const mitk::Mesh *mitk::MeshVtkMapper3D::GetInput() -{ - return static_cast(GetDataNode()->GetData()); -} - -vtkProp *mitk::MeshVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) -{ - return m_PropAssembly; -} - -void mitk::MeshVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) -{ - vtkLinearTransform *vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); - - m_SpheresActor->SetUserTransform(vtktransform); - m_ContourActor->SetUserTransform(vtktransform); -} - -mitk::MeshVtkMapper3D::MeshVtkMapper3D() : m_PropAssembly(nullptr) -{ - m_Spheres = vtkAppendPolyData::New(); - m_Contour = vtkPolyData::New(); - - m_SpheresActor = vtkActor::New(); - m_SpheresMapper = vtkPolyDataMapper::New(); - m_SpheresActor->SetMapper(m_SpheresMapper); - - m_ContourActor = vtkActor::New(); - m_ContourMapper = vtkPolyDataMapper::New(); - m_ContourActor->SetMapper(m_ContourMapper); - m_ContourActor->GetProperty()->SetAmbient(1.0); - - m_PropAssembly = vtkPropAssembly::New(); - - // a vtkPropAssembly is not a sub-class of vtkProp3D, so - // we cannot use m_Prop3D. -} - -mitk::MeshVtkMapper3D::~MeshVtkMapper3D() -{ - m_ContourActor->Delete(); - m_SpheresActor->Delete(); - m_ContourMapper->Delete(); - m_SpheresMapper->Delete(); - m_PropAssembly->Delete(); - m_Spheres->Delete(); - m_Contour->Delete(); -} - -void mitk::MeshVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) -{ - BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer); - bool needGenerateData = ls->IsGenerateDataRequired(renderer, this, GetDataNode()); - - if (needGenerateData) - { - ls->UpdateGenerateDataTime(); - - m_PropAssembly->VisibilityOn(); - - if (m_PropAssembly->GetParts()->IsItemPresent(m_SpheresActor)) - m_PropAssembly->RemovePart(m_SpheresActor); - if (m_PropAssembly->GetParts()->IsItemPresent(m_ContourActor)) - m_PropAssembly->RemovePart(m_ContourActor); - - m_Spheres->RemoveAllInputs(); - m_Contour->Initialize(); - - mitk::Mesh::Pointer input = const_cast(this->GetInput()); - input->Update(); - - mitk::Mesh::DataType::Pointer itkMesh = input->GetMesh(this->GetTimestep()); - - if (itkMesh.GetPointer() == nullptr) - { - m_PropAssembly->VisibilityOff(); - return; - } - - mitk::Mesh::PointsContainer::Iterator i; - - int j; - - float floatRgba[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - double doubleRgba[4] = {1.0f, 1.0f, 1.0f, 1.0f}; - mitk::Color tmpColor; - - // check for color prop and use it for rendering if it exists - m_DataNode->GetColor(floatRgba, nullptr); - - if (dynamic_cast(this->GetDataNode()->GetProperty("unselectedcolor")) != nullptr) - { - tmpColor = dynamic_cast(this->GetDataNode()->GetProperty("unselectedcolor"))->GetValue(); - floatRgba[0] = tmpColor[0]; - floatRgba[1] = tmpColor[1]; - floatRgba[2] = tmpColor[2]; - floatRgba[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value - doubleRgba[0] = floatRgba[0]; - doubleRgba[1] = floatRgba[1]; - doubleRgba[2] = floatRgba[2]; - doubleRgba[3] = floatRgba[3]; - } - - if (itkMesh->GetNumberOfPoints() > 0) - { - // build m_Spheres->GetOutput() vtkPolyData - float pointSize = 2.0; - mitk::FloatProperty::Pointer pointSizeProp = - dynamic_cast(this->GetDataNode()->GetProperty("pointsize")); - if (pointSizeProp.IsNotNull()) - pointSize = pointSizeProp->GetValue(); - - for (j = 0, i = itkMesh->GetPoints()->Begin(); i != itkMesh->GetPoints()->End(); i++, j++) - { - vtkSmartPointer sphere = vtkSmartPointer::New(); - - sphere->SetRadius(pointSize); - sphere->SetCenter(i.Value()[0], i.Value()[1], i.Value()[2]); - - m_Spheres->AddInputConnection(sphere->GetOutputPort()); - sphere->Delete(); - } - - // setup mapper, actor and add to assembly - m_SpheresMapper->SetInputConnection(m_Spheres->GetOutputPort()); - m_SpheresActor->GetProperty()->SetColor(doubleRgba); - m_PropAssembly->AddPart(m_SpheresActor); - } - - if (itkMesh->GetNumberOfCells() > 0) - { -// build m_Contour vtkPolyData -#ifdef VCL_VC60 - itkExceptionMacro(<< "MeshVtkMapper3D currently not working for MS Visual C++ 6.0, because MeshUtils are " - "currently not supported."); -#else - m_Contour = - MeshUtil::MeshToPolyData(itkMesh.GetPointer(), false, false, 0, nullptr, m_Contour); -#endif - - if (m_Contour->GetNumberOfCells() > 0) - { - // setup mapper, actor and add to assembly - m_ContourMapper->SetInputData(m_Contour); - bool wireframe = true; - GetDataNode()->GetVisibility(wireframe, nullptr, "wireframe"); - if (wireframe) - m_ContourActor->GetProperty()->SetRepresentationToWireframe(); - else - m_ContourActor->GetProperty()->SetRepresentationToSurface(); - m_ContourActor->GetProperty()->SetColor(doubleRgba); - m_PropAssembly->AddPart(m_ContourActor); - } - } - } - - bool visible = true; - GetDataNode()->GetVisibility(visible, renderer, "visible"); - - if (!visible) - { - m_SpheresActor->VisibilityOff(); - m_ContourActor->VisibilityOff(); - return; - } - - bool makeContour = false; - this->GetDataNode()->GetBoolProperty("show contour", makeContour); - - if (makeContour) - { - m_ContourActor->VisibilityOn(); - } - else - { - m_ContourActor->VisibilityOff(); - } - - bool showPoints = true; - this->GetDataNode()->GetBoolProperty("show points", showPoints); - if (showPoints) - { - m_SpheresActor->VisibilityOn(); - } - else - { - m_SpheresActor->VisibilityOff(); - } -} - -void mitk::MeshVtkMapper3D::ResetMapper(BaseRenderer * /*renderer*/) -{ - m_PropAssembly->VisibilityOff(); -} diff --git a/Modules/PhotoacousticsLib/include/mitkPASpectralUnmixingFilterBase.h b/Modules/PhotoacousticsLib/include/mitkPASpectralUnmixingFilterBase.h index 80fc069e09..dce6a5d2ce 100644 --- a/Modules/PhotoacousticsLib/include/mitkPASpectralUnmixingFilterBase.h +++ b/Modules/PhotoacousticsLib/include/mitkPASpectralUnmixingFilterBase.h @@ -1,194 +1,194 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef MITKPHOTOACOUSTICSPECTRALUNMIXINGFILTERBASE_H #define MITKPHOTOACOUSTICSPECTRALUNMIXINGFILTERBASE_H #include "mitkImageToImageFilter.h" #include //Includes for smart pointer usage #include "mitkCommon.h" #include "itkLightObject.h" // Includes for AddEnmemberMatrix #include "mitkPAPropertyCalculator.h" #include namespace mitk { namespace pa { /** * \brief The spectral unmixing filter base is designed as superclass for several spectral unmixing filter eg. Eigen- or Vigrabased ones. * One can add wavelengths and chromophores and get a unmixed output images out of one MITK input image using algorithms from the subclasses. * * Input: * The unmixing input has to be a 3D MITK image where the XY-plane is a image and the Z-direction represents recordings for different * wavelengths. Herein a XY-plane for a specific Z-direction will be called "image". Every image has to be assigned to a certain wavelength. * The "AddWavelength" uses "push_back" to write float values into a vector. The first wavelength will correspond to the first image!!! * If there a more input images 'I' then added wavelengths 'w' the filter base interprets the next x images as repetition sequence of the same * wavelengths. If I % w !=0 the surplus image(s) will be dropped. * Addtionaly one has to add chromophores from the property calculator class enum "ChromophoreType" with the "AddChromophore" method. * This method as well uses "push_back" but the chosen (arbitary) order will be the order of the outputs. * * Output: * The output will be one MITK image per chosen chromophore. Where the XY-plane is a image and the Z-direction represents recordings for different * sequences. Furthermore it is possible to creat an output image that contains the information about the relative error between unmixing result * and the input image. * * Subclasses: * - mitkPASpectralUnmixingFilterVigra * - mitkPALinearSpectralUnmixingFilter (uses Eigen algorithms) * - mitkPASpectralUnmixingFilterSimplex * * Possible exceptions: * - "PIXELTYPE ERROR! FLOAT 32 REQUIRED": The MITK input image has to consist out of floats. * - "ERROR! REMOVE WAVELENGTHS!": One needs at least the same amount of images (z-dimension) then added wavelengths. * - "ADD MORE WAVELENGTHS!": One needs at least the same amount of wavelengths then added chromophores. * - "WAVELENGTH XXX nm NOT SUPPORTED!": The wavelength is not part of the proptery calculater data base. The data base can be found @ * [...]/mitk/Modules/PhotoacousticsLib/Resources/spectralLIB.dat * - "ADD OUTPUTS HAS TO BE LARGER THEN ZERO!" * - "NO WAVELENGHTS/CHROMOPHORES SELECZED! * - "INDEX ERROR! NUMBER OF OUTPUTS DOESN'T FIT TO OTHER SETTIGNS!" */ class MITKPHOTOACOUSTICSLIB_EXPORT SpectralUnmixingFilterBase : public mitk::ImageToImageFilter { public: mitkClassMacro(SpectralUnmixingFilterBase, mitk::ImageToImageFilter); /** * \brief AddChromophore takes mitk::pa::PropertyCalculator::ChromophoreType and writes them at the end of the m_Chromophore vector. * The call of the method sets the order of the GetOutput method! * * @param chromophore has to be element of porperty calculater enum chromophore type * @return for wavelength smaller then 300nm and larger then 1000nm the return will be 0, because not at the data base (2018/06/19) */ void AddChromophore(mitk::pa::PropertyCalculator::ChromophoreType chromophore); /** * \brief AddWavelength takes integers and writes them at the end of the m_Wavelength vector. The first call of the method then * corresponds to the first input image and so on. * @param wavelength database supports integers between 300 and 1000 nm */ void AddWavelength(int wavelength); /* * \brief Verbose gives more information to the console. Default value is false. * @param verbose is the boolian to activate the MITK_INFO logged to the console */ virtual void Verbose(bool verbose); /** * \brief AddOutputs takes an integer and sets indexed outputs * @param outputs integer correponds to the number of output images * @throws if outputs == 0 */ virtual void AddOutputs(unsigned int outputs); /* * \brief RelativeError returns a image which compare the L2 norm of the input vector with the unmixing result * @param relativeError is the boolian to activate this tool */ virtual void RelativeError(bool relativeError); /** * \brief AddRelativeErrorSettings takes integers and writes them at the end of the m_RelativeErrorSettings vector. * @param value has to be a integer */ virtual void AddRelativeErrorSettings(int value); - ofstream myfile; // just for testing purposes; has to be removeed + std::ofstream myfile; // just for testing purposes; has to be removeed protected: /** * \brief Constructor creats proptery calculater smart pointer new() */ SpectralUnmixingFilterBase(); ~SpectralUnmixingFilterBase() override; /** * \brief The subclasses will override the mehtod to calculate the spectral unmixing result vector. * @param endmemberMatrix Matrix with number of chromophores colums and number of wavelengths rows so matrix element (i,j) contains * the absorbtion of chromophore j @ wavelength i taken from the database by PropertyElement method. * @param inputVector Vector containing values of one pixel of XY-plane image with number of wavelength rows (z-dimension of a sequenece) * so the pixelvalue of the first wavelength is stored in inputVector[0] and so on. * @throws if algorithm implementiation fails (implemented for the algorithms with critical requirements) */ virtual Eigen::VectorXf SpectralUnmixingAlgorithm(Eigen::Matrix endmemberMatrix, Eigen::VectorXf inputVector) = 0; bool m_Verbose = false; bool m_RelativeError = false; std::vector m_Chromophore; std::vector m_Wavelength; std::vector m_RelativeErrorSettings; private: /* * \brief Initialized output images with the same XY-plane size like the input image and total size in z-direction equals number of sequences. * The pixel type is set to float. * @param totalNumberOfSequences = (unsigned int) (numberOfInputImages / numberOfWavelength) >= 1 */ virtual void InitializeOutputs(unsigned int totalNumberOfSequences); /* * \brief Checks if there are a suitable amount of wavelengths and if the input image consists of floats. * @param input pointer on the MITK input image * @throws if there are more wavelength then images * @throws if there are more chromophores then wavelengths * @throws if the pixel type is not float 32 * @throws if no chromophores or wavelengths selected as input * @throws if the number of indexed outputs does'nt fit to the expected number */ virtual void CheckPreConditions(mitk::Image::Pointer input); /* * \brief Inherit from the "ImageToImageFilter" Superclass. Herain it calls InitializeOutputs, CalculateEndmemberMatrix and * CheckPreConditions methods and enables pixelwise access to do spectral unmixing with the "SpectralUnmixingAlgorithm" * method. In the end the method writes the results into the new MITK output images. */ void GenerateData() override; /* * \brief Creats a Matrix with number of chromophores colums and number of wavelengths rows so matrix element (i,j) contains * the absorbtion of chromophore j @ wavelength i. The absorbtion values are taken from the "PropertyElement" method. * @param m_Chromophore is a vector of "PropertyCalculator::ChromophoreType" containing all selected chromophores for the unmixing * @param m_Wavelength is a vector of integers containing all wavelengths of one sequence */ virtual Eigen::Matrix CalculateEndmemberMatrix( std::vector m_Chromophore, std::vector m_Wavelength); /* * \brief "PropertyElement" is the tool to access the absorbtion values out of the database using mitk::pa::PropertyCalculator::GetAbsorptionForWavelengt * and checks if the requested wavelength is part of the database (not zero values). The "ONEENDMEMBER" is a pseudo absorber with static absorbtion 1 * at every wavelength and is therefor not part of the database. If this one is the selected chromophore the return value is 1 for every wavelength. * @param wavelength has to be integer between 300 and 1000 nm * @param chromophore has to be a mitk::pa::PropertyCalculator::ChromophoreType * @throws if mitk::pa::PropertyCalculator::GetAbsorptionForWavelengt returns 0, because this means that the delivered wavelength is not in the database. */ virtual float PropertyElement(mitk::pa::PropertyCalculator::ChromophoreType, int wavelength); /* * \brief calculates the relative error between the input image and the unmixing result in the L2 norm * @param endmemberMatrix is a Eigen matrix containing the endmember information * @param inputVector is a Eigen vector containing the multispectral information of one pixel * @param resultVector is a Eigen vector containing the spectral unmmixing result */ float CalculateRelativeError(Eigen::Matrix endmemberMatrix, Eigen::VectorXf inputVector, Eigen::VectorXf resultVector); PropertyCalculator::Pointer m_PropertyCalculatorEigen; }; } } #endif // MITKPHOTOACOUSTICSPECTRALUNMIXINGFILTERBASE_ diff --git a/Modules/Remeshing/CMakeLists.txt b/Modules/Remeshing/CMakeLists.txt index 177531d9fe..2697e18603 100644 --- a/Modules/Remeshing/CMakeLists.txt +++ b/Modules/Remeshing/CMakeLists.txt @@ -1,7 +1,9 @@ mitk_create_module( - DEPENDS MitkCore - PACKAGE_DEPENDS ACVD VTK|IOPLY+IOMINC - ) - -add_subdirectory(Testing) + DEPENDS MitkCore + PACKAGE_DEPENDS OpenMesh|OpenMeshTools +) +if(TARGET ${MODULE_TARGET}) + target_link_libraries(${MODULE_TARGET} PRIVATE OpenMeshTools) + target_compile_definitions(${MODULE_TARGET} PRIVATE -D_USE_MATH_DEFINES) +endif() diff --git a/Modules/Remeshing/Testing/CMakeLists.txt b/Modules/Remeshing/Testing/CMakeLists.txt deleted file mode 100644 index a29ccbc947..0000000000 --- a/Modules/Remeshing/Testing/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -if(MITK_USE_ACVD) - MITK_CREATE_MODULE_TESTS() - - mitkAddCustomModuleTest(mitkACVDTest mitkACVDTest ${MITK_DATA_DIR}/binary.stl 0 1228 1.0 10 0.0 1 0 0) -endif() diff --git a/Modules/Remeshing/Testing/files.cmake b/Modules/Remeshing/Testing/files.cmake deleted file mode 100644 index 055665bf46..0000000000 --- a/Modules/Remeshing/Testing/files.cmake +++ /dev/null @@ -1,6 +0,0 @@ -set(MODULE_TESTS -) - -set(MODULE_CUSTOM_TESTS - mitkACVDTest.cpp -) diff --git a/Modules/Remeshing/Testing/mitkACVDTest.cpp b/Modules/Remeshing/Testing/mitkACVDTest.cpp deleted file mode 100644 index f5bf8d5364..0000000000 --- a/Modules/Remeshing/Testing/mitkACVDTest.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#include -#include -#include -#include -#include -#include -#include - -#define _MITK_TEST_FOR_EXCEPTION(STATEMENT, EXCEPTION, MESSAGE) \ - MITK_TEST_OUTPUT_NO_ENDL(<< MESSAGE) \ - try \ - { \ - STATEMENT; \ - MITK_TEST_OUTPUT(<< " [FAILED]") \ - mitk::TestManager::GetInstance()->TestFailed(); \ - } \ - catch (const EXCEPTION &e) \ - { \ - MITK_TEST_OUTPUT(<< "\n " << e.GetDescription() << " [PASSED]") \ - mitk::TestManager::GetInstance()->TestPassed(); \ - } - -template -static T lexical_cast(const std::string &string) -{ - std::istringstream sstream(string); - T value; - - sstream >> value; - - if (sstream.fail()) - { - MITK_ERROR << "Lexical cast failed for '" << string << "'!"; - exit(EXIT_FAILURE); - } - - return value; -} - -static void Remesh_SurfaceIsNull_ThrowsException() -{ - mitk::Surface::ConstPointer surface; - _MITK_TEST_FOR_EXCEPTION( - mitk::ACVD::Remesh(surface, 0, 100, 0.0), mitk::Exception, "Remesh_SurfaceIsNull_ThrowsException") -} - -static void Remesh_PolyDataIsNull_ThrowsException() -{ - mitk::Surface::ConstPointer surface = mitk::Surface::New().GetPointer(); - _MITK_TEST_FOR_EXCEPTION( - mitk::ACVD::Remesh(surface, 0, 100, 0.0), mitk::Exception, "Remesh_PolyDataIsNull_ThrowsException") -} - -static void Remesh_SurfaceDoesNotHaveDataAtTimeStep_ThrowsException() -{ - mitk::Surface::ConstPointer surface = mitk::Surface::New().GetPointer(); - _MITK_TEST_FOR_EXCEPTION(mitk::ACVD::Remesh(surface, 1, 100, 0.0), - mitk::Exception, - "Remesh_SurfaceDoesNotHaveDataAtTimeStep_ThrowsException") -} - -static void Remesh_SurfaceHasNoPolygons_ThrowsException() -{ - mitk::Surface::Pointer surface = mitk::Surface::New(); - vtkSmartPointer polyData = vtkSmartPointer::New(); - surface->SetVtkPolyData(polyData); - _MITK_TEST_FOR_EXCEPTION(mitk::ACVD::Remesh(surface.GetPointer(), 0, 100, 0.0), - mitk::Exception, - "Remesh_SurfaceHasNoPolygons_ThrowsException") -} - -static void Remesh_SurfaceIsValid_ReturnsRemeshedSurface(const std::string &filename, - unsigned int t, - int numVertices, - double gradation, - int subsampling, - double edgeSplitting, - int optimizationLevel, - bool forceManifold, - bool boundaryFixing) -{ - auto surface = mitk::IOUtil::Load(filename); - mitk::Surface::Pointer remeshedSurface = mitk::ACVD::Remesh( - surface.GetPointer(), t, numVertices, gradation, subsampling, edgeSplitting, optimizationLevel, forceManifold, boundaryFixing); - MITK_TEST_CONDITION(remeshedSurface.IsNotNull() && remeshedSurface->GetVtkPolyData() != nullptr && - remeshedSurface->GetVtkPolyData()->GetNumberOfPolys() != 0, - "Remesh_SurfaceIsValid_ReturnsRemeshedSurface") -} - -int mitkACVDTest(int argc, char *argv[]) -{ - if (argc != 10) - { - MITK_ERROR << "Invalid argument count!\n" - << "Usage: mitkACVDTest \n" - << " \n" - << " \n" - << " See MITK API documentation of mitk::ACVD::Remesh() for details."; - - return EXIT_FAILURE; - } - - const std::string filename = argv[1]; - const unsigned int t = lexical_cast(argv[2]); - const int numVertices = lexical_cast(argv[3]); - const double gradation = lexical_cast(argv[4]); - const int subsampling = lexical_cast(argv[5]); - const double edgeSplitting = lexical_cast(argv[6]); - const int optimizationLevel = lexical_cast(argv[7]); - const bool forceManifold = lexical_cast(argv[8]); - const bool boundaryFixing = lexical_cast(argv[9]); - - MITK_TEST_BEGIN("mitkACVDTest") - - vtkDebugLeaks::SetExitError(0); - - Remesh_SurfaceIsNull_ThrowsException(); - Remesh_PolyDataIsNull_ThrowsException(); - Remesh_SurfaceDoesNotHaveDataAtTimeStep_ThrowsException(); - Remesh_SurfaceHasNoPolygons_ThrowsException(); - - Remesh_SurfaceIsValid_ReturnsRemeshedSurface( - filename, t, numVertices, gradation, subsampling, edgeSplitting, optimizationLevel, forceManifold, boundaryFixing); - - MITK_TEST_END() -} diff --git a/Modules/Remeshing/files.cmake b/Modules/Remeshing/files.cmake index a9a6a7d8eb..303e7498dd 100644 --- a/Modules/Remeshing/files.cmake +++ b/Modules/Remeshing/files.cmake @@ -1,3 +1,7 @@ +set(H_FILES + include/mitkRemeshing.h +) + set(CPP_FILES - mitkACVD.cpp + mitkRemeshing.cpp ) diff --git a/Modules/Remeshing/include/mitkRemeshing.h b/Modules/Remeshing/include/mitkRemeshing.h new file mode 100644 index 0000000000..ef068d6424 --- /dev/null +++ b/Modules/Remeshing/include/mitkRemeshing.h @@ -0,0 +1,39 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#ifndef mitkRemeshing_h +#define mitkRemeshing_h + +#include +#include + +namespace mitk +{ + namespace Remeshing + { + /** \brief Reduce the number of vertices of an mitk::Surface. + * + * The decimation is applied separately to all time steps of the input surface. + * The meshes of the resulting surface are guaranteed to consist of triangles only. + * + * \param[in] input Input surface + * \param[in] percent Relative number of vertices after decimation [0, 1] + * \param[in] calculateNormals Calculate normals after decimation (\c true by default) + * \param[in] flipNormals Flip calculated normals (\c false by default) + * + * \return Decimated surface + */ + MITKREMESHING_EXPORT Surface::Pointer Decimate(const Surface* input, double percent, bool calculateNormals = true, bool flipNormals = false); + } +} + +#endif diff --git a/Modules/Remeshing/mitkACVD.cpp b/Modules/Remeshing/mitkACVD.cpp deleted file mode 100644 index f805979d52..0000000000 --- a/Modules/Remeshing/mitkACVD.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#include "mitkACVD.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct ClustersQuadrics -{ - explicit ClustersQuadrics(int size) : Elements(new double *[size]), Size(size) - { - for (int i = 0; i < size; ++i) - { - Elements[i] = new double[9]; - - for (int j = 0; j < 9; ++j) - Elements[i][j] = 0.0; - } - } - - ~ClustersQuadrics() - { - for (int i = 0; i < Size; ++i) - delete[] Elements[i]; - - delete Elements; - } - - double **Elements; - int Size; - -private: - ClustersQuadrics(const ClustersQuadrics &); - ClustersQuadrics &operator=(const ClustersQuadrics &); -}; - -static void ValidateSurface(mitk::Surface::ConstPointer surface, unsigned int t) -{ - if (surface.IsNull()) - mitkThrow() << "Input surface is nullptr!"; - - if (t >= surface->GetSizeOfPolyDataSeries()) - mitkThrow() << "Input surface doesn't have data at time step " << t << "!"; - - vtkPolyData *polyData = const_cast(surface.GetPointer())->GetVtkPolyData(t); - - if (polyData == nullptr) - mitkThrow() << "PolyData of input surface at time step " << t << " is nullptr!"; - - if (polyData->GetNumberOfPolys() == 0) - mitkThrow() << "Input surface has no polygons at time step " << t << "!"; -} - -mitk::Surface::Pointer mitk::ACVD::Remesh(mitk::Surface::ConstPointer surface, - unsigned int t, - int numVertices, - double gradation, - int subsampling, - double edgeSplitting, - int optimizationLevel, - bool forceManifold, - bool boundaryFixing) -{ - ValidateSurface(surface, t); - - MITK_INFO << "Start remeshing..."; - - vtkSmartPointer surfacePolyData = vtkSmartPointer::New(); - surfacePolyData->DeepCopy(const_cast(surface.GetPointer())->GetVtkPolyData(t)); - - vtkSmartPointer mesh = vtkSmartPointer::New(); - - mesh->CreateFromPolyData(surfacePolyData); - mesh->GetCellData()->Initialize(); - mesh->GetPointData()->Initialize(); - - mesh->DisplayMeshProperties(); - - if (numVertices == 0) - numVertices = surfacePolyData->GetNumberOfPoints(); - - if (edgeSplitting != 0.0) - mesh->SplitLongEdges(edgeSplitting); - - vtkSmartPointer remesher = vtkSmartPointer::New(); - - remesher->GetMetric()->SetGradation(gradation); - remesher->SetBoundaryFixing(boundaryFixing); - remesher->SetConsoleOutput(1); - remesher->SetForceManifold(forceManifold); - remesher->SetInput(mesh); - remesher->SetNumberOfClusters(numVertices); - remesher->SetNumberOfThreads(vtkMultiThreader::GetGlobalDefaultNumberOfThreads()); - remesher->SetSubsamplingThreshold(subsampling); - - remesher->Remesh(); - - // Optimization: Minimize distance between input surface and remeshed surface - if (optimizationLevel != 0) - { - ClustersQuadrics clustersQuadrics(numVertices); - - vtkSmartPointer faceList = vtkSmartPointer::New(); - vtkSmartPointer clustering = remesher->GetClustering(); - vtkSmartPointer remesherInput = remesher->GetInput(); - int clusteringType = remesher->GetClusteringType(); - int numItems = remesher->GetNumberOfItems(); - int numMisclassifiedItems = 0; - - for (int i = 0; i < numItems; ++i) - { - int cluster = clustering->GetValue(i); - - if (cluster >= 0 && cluster < numVertices) - { - if (clusteringType != 0) - { - remesherInput->GetVertexNeighbourFaces(i, faceList); - int numIds = static_cast(faceList->GetNumberOfIds()); - - for (int j = 0; j < numIds; ++j) - vtkQuadricTools::AddTriangleQuadric( - clustersQuadrics.Elements[cluster], remesherInput, faceList->GetId(j), false); - } - else - { - vtkQuadricTools::AddTriangleQuadric(clustersQuadrics.Elements[cluster], remesherInput, i, false); - } - } - else - { - ++numMisclassifiedItems; - } - } - - if (numMisclassifiedItems != 0) - std::cout << numMisclassifiedItems << " items with wrong cluster association" << std::endl; - - vtkSmartPointer remesherOutput = remesher->GetOutput(); - double point[3]; - - for (int i = 0; i < numVertices; ++i) - { - remesherOutput->GetPoint(i, point); - vtkQuadricTools::ComputeRepresentativePoint(clustersQuadrics.Elements[i], point, optimizationLevel); - remesherOutput->SetPointCoordinates(i, point); - } - - std::cout << "After quadrics post-processing:" << std::endl; - remesherOutput->DisplayMeshProperties(); - } - - vtkSmartPointer normals = vtkSmartPointer::New(); - - normals->SetInputData(remesher->GetOutput()); - normals->AutoOrientNormalsOn(); - normals->ComputeCellNormalsOff(); - normals->ComputePointNormalsOn(); - normals->ConsistencyOff(); - normals->FlipNormalsOff(); - normals->NonManifoldTraversalOff(); - normals->SplittingOff(); - - normals->Update(); - - Surface::Pointer remeshedSurface = Surface::New(); - remeshedSurface->SetVtkPolyData(normals->GetOutput()); - - MITK_INFO << "Finished remeshing"; - - return remeshedSurface; -} - -mitk::ACVD::RemeshFilter::RemeshFilter() - : m_TimeStep(0), - m_NumVertices(0), - m_Gradation(1.0), - m_Subsampling(10), - m_EdgeSplitting(0.0), - m_OptimizationLevel(1), - m_ForceManifold(false), - m_BoundaryFixing(false) -{ - Surface::Pointer output = Surface::New(); - this->SetNthOutput(0, output); -} - -mitk::ACVD::RemeshFilter::~RemeshFilter() -{ -} - -void mitk::ACVD::RemeshFilter::GenerateData() -{ - Surface::Pointer output = Remesh(this->GetInput(), - m_TimeStep, - m_NumVertices, - m_Gradation, - m_Subsampling, - m_EdgeSplitting, - m_OptimizationLevel, - m_ForceManifold, - m_BoundaryFixing); - this->SetNthOutput(0, output); -} diff --git a/Modules/Remeshing/mitkACVD.h b/Modules/Remeshing/mitkACVD.h deleted file mode 100644 index ca83919d84..0000000000 --- a/Modules/Remeshing/mitkACVD.h +++ /dev/null @@ -1,102 +0,0 @@ -/*============================================================================ - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center (DKFZ) -All rights reserved. - -Use of this source code is governed by a 3-clause BSD license that can be -found in the LICENSE file. - -============================================================================*/ - -#ifndef mitkACVD_h -#define mitkACVD_h - -#include -#include -#include - -namespace mitk -{ - namespace ACVD - { - /** \brief Remesh a surface and store the result in a new surface. - * - * The %ACVD library is used for remeshing which is based on the paper "Approximated Centroidal Voronoi Diagrams for - * Uniform Polygonal Mesh Coarsening" by S. Valette, and J. M. Chassery. - * There are a few rules of thumbs regarding the ranges of parameters to gain high quality remeshed surfaces: - * - *
    - *
  • numVertices is exact, however, if boundaryFixing is enabled, additional vertices are generated at - * boundaries - *
  • %Set gradation to zero in case you want polygons of roughly the same size all over the remeshed surface; - * start with 1 otherwise - *
  • subsampling has direct influence on the quality of the remeshed surface (higher values take more time) - *
  • edgeSplitting is useful for surfaces that contain long and thin triangles but takes a long time - *
  • Leave optimizationLevel set to 1 as greater values result in degenerated polygons - *
  • Irregular shrinking of boundaries during remeshing can be avoided by boundaryFixing, however this results - * in additional, lower quality polygons at boundaries - *
- * - * \param[in] surface Input surface. - * \param[in] t Time step of a four-dimensional input surface, zero otherwise. - * \param[in] numVertices Desired number of vertices in the remeshed surface, set to zero to keep original vertex - * count. - * \param[in] gradation Influence of surface curvature on polygon size. - * \param[in] subsampling Subsample input surface until number of vertices exceeds initial count times this - * parameter. - * \param[in] edgeSplitting Recursively split edges that are longer than the average edge length times this - * parameter. - * \param[in] optimizationLevel Minimize distance between input surface and remeshed surface. - * \param[in] forceManifold - * \param[in] boundaryFixing Keep original surface boundaries by adding additional polygons. - * \return Returns the remeshed surface or nullptr if input surface is invalid. - */ - MITKREMESHING_EXPORT Surface::Pointer Remesh(Surface::ConstPointer surface, - unsigned int t, - int numVertices, - double gradation, - int subsampling = 10, - double edgeSplitting = 0.0, - int optimizationLevel = 1, - bool forceManifold = false, - bool boundaryFixing = false); - - /** \brief Encapsulates mitk::ACVD::Remesh function as filter. - */ - class MITKREMESHING_EXPORT RemeshFilter : public mitk::SurfaceToSurfaceFilter - { - public: - mitkClassMacro(RemeshFilter, SurfaceToSurfaceFilter); - itkFactorylessNewMacro(Self); - itkCloneMacro(Self); - itkSetMacro(TimeStep, unsigned int); - itkSetMacro(NumVertices, int); - itkSetMacro(Gradation, double); - itkSetMacro(Subsampling, int); - itkSetMacro(EdgeSplitting, double); - itkSetMacro(OptimizationLevel, int); - itkSetMacro(ForceManifold, bool); - itkSetMacro(BoundaryFixing, bool); - - protected: - void GenerateData() override; - - private: - RemeshFilter(); - ~RemeshFilter() override; - - unsigned int m_TimeStep; - int m_NumVertices; - double m_Gradation; - int m_Subsampling; - double m_EdgeSplitting; - int m_OptimizationLevel; - bool m_ForceManifold; - bool m_BoundaryFixing; - }; - } -} - -#endif diff --git a/Modules/Remeshing/src/mitkRemeshing.cpp b/Modules/Remeshing/src/mitkRemeshing.cpp new file mode 100644 index 0000000000..dd531cfaaf --- /dev/null +++ b/Modules/Remeshing/src/mitkRemeshing.cpp @@ -0,0 +1,185 @@ +/*============================================================================ + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center (DKFZ) +All rights reserved. + +Use of this source code is governed by a 3-clause BSD license that can be +found in the LICENSE file. + +============================================================================*/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using Mesh = OpenMesh::TriMesh_ArrayKernelT; + +namespace +{ + bool IsValidPolyData(vtkPolyData* polyData) + { + return nullptr != polyData && 0 < polyData->GetNumberOfPoints() && + (0 < polyData->GetNumberOfPolys() || 0 < polyData->GetNumberOfStrips()); + } + + vtkSmartPointer TriangulatePolyData(vtkPolyData* polyData) + { + auto triangleFilter = vtkSmartPointer::New(); + triangleFilter->SetInputData(polyData); + triangleFilter->PassVertsOff(); + triangleFilter->PassLinesOff(); + + triangleFilter->Update(); + + return triangleFilter->GetOutput(); + } + + vtkSmartPointer CalculateNormals(vtkPolyData* polyData, bool flipNormals) + { + auto polyDataNormals = vtkSmartPointer::New(); + polyDataNormals->SetInputData(polyData); + + if (flipNormals) + polyDataNormals->FlipNormalsOn(); + + polyDataNormals->Update(); + + return polyDataNormals->GetOutput(); + } + + Mesh ConvertPolyDataToMesh(vtkPolyData* polyData) + { + Mesh mesh; + + auto* points = polyData->GetPoints(); + const auto numPoints = points->GetNumberOfPoints(); + + for (std::remove_const_t i = 0; i < numPoints; ++i) + mesh.add_vertex(Mesh::Point(points->GetPoint(i))); + + auto* polys = polyData->GetPolys(); + const auto numPolys = polys->GetNumberOfCells(); + + auto ids = vtkSmartPointer::New(); + std::array vertexHandles; + + for (std::remove_const_t i = 0; i < numPolys; ++i) + { + polys->GetCellAtId(i, ids); + + vertexHandles[0] = Mesh::VertexHandle(static_cast(ids->GetId(0))); + vertexHandles[1] = Mesh::VertexHandle(static_cast(ids->GetId(1))); + vertexHandles[2] = Mesh::VertexHandle(static_cast(ids->GetId(2))); + + mesh.add_face(vertexHandles.data(), 3); + } + + return mesh; + } + + vtkSmartPointer ConvertMeshToPolyData(const Mesh& mesh) + { + auto polyData = vtkSmartPointer::New(); + + const auto numVertices = mesh.n_vertices(); + auto points = vtkSmartPointer::New(); + points->SetNumberOfPoints(numVertices); + + for (std::remove_const_t i = 0; i < numVertices; ++i) + points->SetPoint(i, mesh.point(Mesh::VertexHandle(static_cast(i))).data()); + + polyData->SetPoints(points); + + const auto numFaces = mesh.n_faces(); + auto polys = vtkSmartPointer::New(); + + auto ids = vtkSmartPointer::New(); + ids->SetNumberOfIds(3); + Mesh::CFVIter iter; + + for (std::remove_const_t i = 0; i < numFaces; ++i) + { + iter = mesh.cfv_iter(Mesh::FaceHandle(static_cast(i))); + + ids->SetId(0, (iter++)->idx()); + ids->SetId(1, (iter++)->idx()); + ids->SetId(2, iter->idx()); + + polys->InsertNextCell(ids); + } + + polyData->SetPolys(polys); + + return polyData; + } + + mitk::Surface::Pointer ProcessEachTimeStep(const mitk::Surface* input, bool calculateNormals, bool flipNormals, const std::function& ProcessMesh) + { + if (nullptr == input || !input->IsInitialized()) + return nullptr; + + auto output = mitk::Surface::New(); + const auto numTimeSteps = input->GetTimeSteps(); + + for (std::remove_const_t t = 0; t < numTimeSteps; ++t) + { + vtkSmartPointer polyData = input->GetVtkPolyData(t); + + if (IsValidPolyData(polyData)) + { + polyData = TriangulatePolyData(polyData); + + if (IsValidPolyData(polyData)) + { + auto mesh = ConvertPolyDataToMesh(polyData); + ProcessMesh(mesh); + polyData = ConvertMeshToPolyData(mesh); + + if (calculateNormals) + polyData = CalculateNormals(polyData, flipNormals); + + output->SetVtkPolyData(polyData, t); + continue; + } + } + + output->SetVtkPolyData(nullptr, t); + } + + return output; + } +} + +mitk::Surface::Pointer mitk::Remeshing::Decimate(const Surface* input, double percent, bool calculateNormals, bool flipNormals) +{ + return ProcessEachTimeStep(input, calculateNormals, flipNormals, [percent](Mesh& mesh) { + using Decimater = OpenMesh::Decimater::DecimaterT; + using HModQuadric = OpenMesh::Decimater::ModQuadricT::Handle; + + Decimater decimater(mesh); + + HModQuadric hModQuadric; + decimater.add(hModQuadric); + decimater.module(hModQuadric).unset_max_err(); + + decimater.initialize(); + decimater.decimate_to(mesh.n_vertices() * std::max(0.0, std::min(percent, 1.0))); + + mesh.garbage_collection(); + }); +} diff --git a/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp b/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp index 9171a6ce5b..c6cfe3b656 100644 --- a/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp +++ b/Modules/SceneSerializationBase/test/mitkPropertySerializationTest.cpp @@ -1,273 +1,199 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "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 "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("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("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 - OdfImage - 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 (auto 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."); } auto *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/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/QmitkPAUSViewerView.cpp b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/QmitkPAUSViewerView.cpp index b3191afbf9..c5952656d8 100644 --- a/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/QmitkPAUSViewerView.cpp +++ b/Plugins/org.mitk.gui.qt.photoacoustics.pausviewer/src/QmitkPAUSViewerView.cpp @@ -1,155 +1,155 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // Blueberry #include #include #include "mitkScaleLegendAnnotation.h" #include "mitkLayoutAnnotationRenderer.h" #include "mitkManualPlacementAnnotationRenderer.h" #include "mitkTextAnnotation2D.h" #include "QmitkPAUSViewerView.h" const std::string QmitkPAUSViewerView::VIEW_ID = "org.mitk.views.photoacoustics.pausviewer"; QmitkPAUSViewerView::QmitkPAUSViewerView() : m_PADataStorage(mitk::StandaloneDataStorage::New()), m_USDataStorage(mitk::StandaloneDataStorage::New()), m_UltrasoundReference(nullptr) { } QmitkPAUSViewerView::~QmitkPAUSViewerView() { if(m_UltrasoundReference != nullptr) *m_UltrasoundReference = nullptr; } void QmitkPAUSViewerView::InitWindows() { AddOverlays(); } void QmitkPAUSViewerView::SetFocus() { } void QmitkPAUSViewerView::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, const QList& /*nodes*/) { } void QmitkPAUSViewerView::CreateQtPartControl(QWidget *parent) { m_Controls = new Ui::QmitkPAUSViewerViewControls; m_Controls->setupUi(parent); m_Controls->m_PARenderWindow->GetRenderer()->SetDataStorage(m_PADataStorage); m_Controls->m_USRenderWindow->GetRenderer()->SetDataStorage(m_USDataStorage); } void QmitkPAUSViewerView::SetPADataStorage(mitk::StandaloneDataStorage::Pointer paStore) { if (m_Controls == nullptr) return; m_PADataStorage = paStore; m_Controls->m_PARenderWindow->GetRenderer()->SetDataStorage(m_PADataStorage); m_Controls->m_PALevelWindow->SetDataStorage(m_PADataStorage); } void QmitkPAUSViewerView::SetUSDataStorage(mitk::StandaloneDataStorage::Pointer usStore) { if (m_Controls == nullptr) return; m_USDataStorage = usStore; m_Controls->m_USRenderWindow->GetRenderer()->SetDataStorage(m_USDataStorage); m_Controls->m_USLevelWindow->SetDataStorage(m_USDataStorage); } vtkRenderWindow* QmitkPAUSViewerView::GetPARenderWindow() { if (m_Controls == nullptr) return nullptr; - return m_Controls->m_PARenderWindow->GetRenderWindow(); + return m_Controls->m_PARenderWindow->renderWindow(); } vtkRenderWindow* QmitkPAUSViewerView::GetUSRenderWindow() { if (m_Controls == nullptr) return nullptr; - return m_Controls->m_USRenderWindow->GetRenderWindow(); + return m_Controls->m_USRenderWindow->renderWindow(); } void QmitkPAUSViewerView::AddOverlays() { //if (m_PARenderer == nullptr || /*m_PAOverlayController == nullptr||*/ m_USRenderer == nullptr /*|| m_USOverlayController == nullptr*/) //{ m_PARenderer = mitk::BaseRenderer::GetInstance(GetPARenderWindow()); m_USRenderer = mitk::BaseRenderer::GetInstance(GetUSRenderWindow()); //} MITK_INFO << "1111111111111111111111"; mitk::ScaleLegendAnnotation::Pointer scaleAnnotation = mitk::ScaleLegendAnnotation::New(); //scaleAnnotation->SetLeftAxisVisibility(true); //scaleAnnotation->SetRightAxisVisibility(false); //scaleAnnotation->SetRightAxisVisibility(false); //scaleAnnotation->SetTopAxisVisibility(false); //scaleAnnotation->SetCornerOffsetFactor(0); MITK_INFO << "1111111111111111111111"; // Add Overlays //![TextAnnotation2D] // Create a textAnnotation2D mitk::TextAnnotation2D::Pointer textAnnotation = mitk::TextAnnotation2D::New(); textAnnotation->SetText("Test!"); // set UTF-8 encoded text to render textAnnotation->SetFontSize(40); textAnnotation->SetColor(1, 0, 0); // Set text color to red textAnnotation->SetOpacity(0.5); MITK_INFO << "1111111111111111111111"; // The position of the Annotation can be set to a fixed coordinate on the display. mitk::Point2D pos; pos[0] = 10; pos[1] = 20; textAnnotation->SetPosition2D(pos); MITK_INFO << "1111111111111111111111"; std::string rendererID = m_PARenderer->GetName(); // The LayoutAnnotationRenderer can place the TextAnnotation2D at some defined corner positions mitk::LayoutAnnotationRenderer::AddAnnotation( textAnnotation, rendererID, mitk::LayoutAnnotationRenderer::TopLeft, 5, 5, 1); mitk::LayoutAnnotationRenderer::AddAnnotation( textAnnotation, m_PARenderer.GetPointer(), mitk::LayoutAnnotationRenderer::TopLeft, 5, 5, 1); mitk::ManualPlacementAnnotationRenderer::AddAnnotation( textAnnotation, m_PARenderer.GetPointer()); MITK_INFO << "1111111111111111111111"; mitk::LayoutAnnotationRenderer::AddAnnotation(scaleAnnotation.GetPointer(), m_PARenderer->GetName(), mitk::LayoutAnnotationRenderer::TopLeft, 5, 5, 1); mitk::LayoutAnnotationRenderer::AddAnnotation(scaleAnnotation.GetPointer(), m_USRenderer, mitk::LayoutAnnotationRenderer::TopLeft, 5, 5, 1); MITK_INFO << "1111111111111111111111"; } void QmitkPAUSViewerView::RemoveOverlays() { // m_PAOverlayManager->RemoveAllOverlays(); } void QmitkPAUSViewerView::SetUltrasoundReference(QmitkPAUSViewerView** ultrasoundReference) { m_UltrasoundReference = ultrasoundReference; } diff --git a/Plugins/org.mitk.gui.qt.remeshing/CMakeLists.txt b/Plugins/org.mitk.gui.qt.remeshing/CMakeLists.txt index 0c79a9f4d2..dcfeabfa2f 100644 --- a/Plugins/org.mitk.gui.qt.remeshing/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.remeshing/CMakeLists.txt @@ -1,10 +1,7 @@ project(org_mitk_gui_qt_remeshing) -include_directories(${CTK_INCLUDE_DIRS}) - mitk_create_plugin( EXPORT_DIRECTIVE REMESHING_EXPORT EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgets MitkRemeshing - PACKAGE_DEPENDS Qt5|OpenGL+Xml ) diff --git a/Plugins/org.mitk.gui.qt.remeshing/files.cmake b/Plugins/org.mitk.gui.qt.remeshing/files.cmake index ef654235b4..5f5abb5665 100644 --- a/Plugins/org.mitk.gui.qt.remeshing/files.cmake +++ b/Plugins/org.mitk.gui.qt.remeshing/files.cmake @@ -1,36 +1,36 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES - org_mitk_gui_qt_remeshing_Activator.cpp + QmitkPluginActivator.cpp QmitkRemeshingView.cpp ) set(UI_FILES src/internal/QmitkRemeshingViewControls.ui ) set(MOC_H_FILES - src/internal/org_mitk_gui_qt_remeshing_Activator.h + src/internal/QmitkPluginActivator.h src/internal/QmitkRemeshingView.h ) set(CACHED_RESOURCE_FILES resources/RemeshingIcon.svg plugin.xml ) set(QRC_FILES resources/Remeshing.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach() foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach() diff --git a/Plugins/org.mitk.gui.qt.remeshing/src/internal/org_mitk_gui_qt_remeshing_Activator.cpp b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkPluginActivator.cpp similarity index 70% rename from Plugins/org.mitk.gui.qt.remeshing/src/internal/org_mitk_gui_qt_remeshing_Activator.cpp rename to Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkPluginActivator.cpp index 80e2706759..44cc9e175b 100644 --- a/Plugins/org.mitk.gui.qt.remeshing/src/internal/org_mitk_gui_qt_remeshing_Activator.cpp +++ b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkPluginActivator.cpp @@ -1,23 +1,23 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ -#include "org_mitk_gui_qt_remeshing_Activator.h" +#include "QmitkPluginActivator.h" #include "QmitkRemeshingView.h" -void mitk::org_mitk_gui_qt_remeshing_Activator::start(ctkPluginContext* context) +void QmitkPluginActivator::start(ctkPluginContext* context) { BERRY_REGISTER_EXTENSION_CLASS(QmitkRemeshingView, context); } -void mitk::org_mitk_gui_qt_remeshing_Activator::stop(ctkPluginContext*) +void QmitkPluginActivator::stop(ctkPluginContext*) { } diff --git a/Plugins/org.mitk.gui.qt.remeshing/src/internal/org_mitk_gui_qt_remeshing_Activator.h b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkPluginActivator.h similarity index 50% rename from Plugins/org.mitk.gui.qt.remeshing/src/internal/org_mitk_gui_qt_remeshing_Activator.h rename to Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkPluginActivator.h index bde213bb43..eeb34e8cb1 100644 --- a/Plugins/org.mitk.gui.qt.remeshing/src/internal/org_mitk_gui_qt_remeshing_Activator.h +++ b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkPluginActivator.h @@ -1,32 +1,29 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ -#ifndef org_mitk_gui_qt_remeshing_Activator_h -#define org_mitk_gui_qt_remeshing_Activator_h +#ifndef QmitkPluginActivator_h +#define QmitkPluginActivator_h #include -namespace mitk +class QmitkPluginActivator : public QObject, public ctkPluginActivator { - class org_mitk_gui_qt_remeshing_Activator : public QObject, public ctkPluginActivator - { - Q_OBJECT - Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_remeshing") - Q_INTERFACES(ctkPluginActivator) - - public: - void start(ctkPluginContext* context) override; - void stop(ctkPluginContext* context) override; - }; -} + Q_OBJECT + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_remeshing") + Q_INTERFACES(ctkPluginActivator) + +public: + void start(ctkPluginContext* context) override; + void stop(ctkPluginContext* context) override; +}; #endif diff --git a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.cpp b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.cpp index 9e230b5dfc..9ed0a2ef58 100644 --- a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.cpp +++ b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.cpp @@ -1,163 +1,123 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #include "QmitkRemeshingView.h" +#include + #include -#include #include #include #include #include #include -#include -#include - -#include -#include +#include const std::string QmitkRemeshingView::VIEW_ID = "org.mitk.views.remeshing"; QmitkRemeshingView::QmitkRemeshingView() + : m_Controls(new Ui::QmitkRemeshingViewControls) { } QmitkRemeshingView::~QmitkRemeshingView() { } void QmitkRemeshingView::CreateQtPartControl(QWidget* parent) { - m_Controls.setupUi(parent); + m_Controls->setupUi(parent); - m_Controls.remeshPushButton->setIcon(berry::QtStyleManager::ThemeIcon(QStringLiteral(":/Remeshing/RemeshingIcon.svg"))); + m_Controls->decimatePushButton->setIcon(berry::QtStyleManager::ThemeIcon(QStringLiteral(":/Remeshing/RemeshingIcon.svg"))); - m_Controls.selectionWidget->SetDataStorage(this->GetDataStorage()); - m_Controls.selectionWidget->SetSelectionIsOptional(true); - m_Controls.selectionWidget->SetEmptyInfo(QStringLiteral("Select a surface")); - m_Controls.selectionWidget->SetAutoSelectNewNodes(true); - m_Controls.selectionWidget->SetNodePredicate(mitk::NodePredicateAnd::New( + m_Controls->selectionWidget->SetDataStorage(this->GetDataStorage()); + m_Controls->selectionWidget->SetSelectionIsOptional(true); + m_Controls->selectionWidget->SetEmptyInfo(QStringLiteral("Select a surface")); + m_Controls->selectionWidget->SetAutoSelectNewNodes(true); + m_Controls->selectionWidget->SetNodePredicate(mitk::NodePredicateAnd::New( mitk::TNodePredicateDataType::New(), mitk::NodePredicateNot::New(mitk::NodePredicateOr::New( mitk::NodePredicateProperty::New("helper object"), mitk::NodePredicateProperty::New("hidden object"))))); - connect(m_Controls.selectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkRemeshingView::OnSelectedSurfaceChanged); - connect(m_Controls.densitySlider, SIGNAL(valueChanged(int)), this, SLOT(OnDensityChanged(int))); - connect(m_Controls.densitySpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnDensityChanged(int))); - connect(m_Controls.remeshPushButton, SIGNAL(clicked()), this, SLOT(OnRemeshButtonClicked())); + connect(m_Controls->selectionWidget, &QmitkSingleNodeSelectionWidget::CurrentSelectionChanged, this, &QmitkRemeshingView::OnSurfaceChanged); + connect(m_Controls->polygonCountSlider, SIGNAL(valueChanged(int)), this, SLOT(OnPolygonCountChanged(int))); + connect(m_Controls->polygonCountSpinBox, SIGNAL(valueChanged(int)), this, SLOT(OnPolygonCountChanged(int))); + connect(m_Controls->calculateNormalsCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnCalculateNormalsChanged(int))); + connect(m_Controls->decimatePushButton, SIGNAL(clicked()), this, SLOT(OnDecimateButtonClicked())); - this->OnSelectedSurfaceChanged(m_Controls.selectionWidget->GetSelectedNodes()); + this->OnSurfaceChanged(m_Controls->selectionWidget->GetSelectedNodes()); } -void QmitkRemeshingView::OnSelectedSurfaceChanged(const QmitkSingleNodeSelectionWidget::NodeList& nodes) +void QmitkRemeshingView::OnSurfaceChanged(const QmitkSingleNodeSelectionWidget::NodeList& nodes) { - if (!nodes.empty() && nodes.front().IsNotNull()) - { - m_MaxNumberOfVertices = static_cast(static_cast(nodes.front()->GetData())->GetVtkPolyData()->GetNumberOfPoints()); - this->EnableWidgets(true); - } - else - { - m_MaxNumberOfVertices = 0; - this->EnableWidgets(false); - } + this->EnableWidgets(!nodes.empty() && nodes.front().IsNotNull()); } -void QmitkRemeshingView::OnDensityChanged(int density) +void QmitkRemeshingView::OnPolygonCountChanged(int polygonCount) { - if (density != m_Controls.densitySlider->value()) - m_Controls.densitySlider->setValue(density); + if (polygonCount != m_Controls->polygonCountSlider->value()) + m_Controls->polygonCountSlider->setValue(polygonCount); - if (density != m_Controls.densitySpinBox->value()) - m_Controls.densitySpinBox->setValue(density); + if (polygonCount != m_Controls->polygonCountSpinBox->value()) + m_Controls->polygonCountSpinBox->setValue(polygonCount); } -void QmitkRemeshingView::OnRemeshButtonClicked() +void QmitkRemeshingView::OnCalculateNormalsChanged(int checkState) { - mitk::DataNode::Pointer selectedNode = m_Controls.selectionWidget->GetSelectedNode(); - mitk::Surface::ConstPointer surface = static_cast(selectedNode->GetData()); - - int density = m_Controls.densitySpinBox->value(); - int numVertices = std::max(100, static_cast(m_MaxNumberOfVertices * (density * 0.01))); - - double gradation = m_Controls.remeshingComboBox->currentText() == QStringLiteral("Adaptive") - ? 1.0 - : 0.0; - - const QString quality = m_Controls.qualityComboBox->currentText(); - int subsampling; - - if (QStringLiteral("High (slow)") == quality) - { - subsampling = 50; - } - else if (QStringLiteral("Maximum (very slow)") == quality) - { - subsampling = 500; - } - else // The default is "Medium (fast)". - { - subsampling = 10; - } - - bool boundaryFixing = m_Controls.preserveEdgesCheckBox->isChecked(); + m_Controls->flipNormalsCheckBox->setEnabled(Qt::Unchecked != checkState); +} - mitk::ACVD::RemeshFilter::Pointer remesher = mitk::ACVD::RemeshFilter::New(); - remesher->SetInput(surface); - remesher->SetTimeStep(0); - remesher->SetNumVertices(numVertices); - remesher->SetGradation(gradation); - remesher->SetSubsampling(subsampling); - remesher->SetEdgeSplitting(0.0); - remesher->SetOptimizationLevel(1.0); - remesher->SetForceManifold(false); - remesher->SetBoundaryFixing(boundaryFixing); +void QmitkRemeshingView::OnDecimateButtonClicked() +{ + mitk::DataNode::Pointer selectedNode = m_Controls->selectionWidget->GetSelectedNode(); + mitk::Surface::ConstPointer input = static_cast(selectedNode->GetData()); + mitk::Surface::Pointer output; try { - remesher->Update(); + output = mitk::Remeshing::Decimate(input, + 0.01 * m_Controls->polygonCountSpinBox->value(), + m_Controls->calculateNormalsCheckBox->isChecked(), + m_Controls->flipNormalsCheckBox->isChecked()); } catch(const mitk::Exception& exception) { MITK_ERROR << exception.GetDescription(); return; } - mitk::Surface::Pointer remeshedSurface = remesher->GetOutput(); + if (output.IsNull()) + return; - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - newNode->SetName(QString("%1 (%2%)").arg(selectedNode->GetName().c_str()).arg(density).toStdString()); - newNode->SetProperty("material.representation", mitk::VtkRepresentationProperty::New(VTK_WIREFRAME)); - newNode->SetData(remeshedSurface); + auto newNode = mitk::DataNode::New(); + newNode->SetName(QString("%1 (decimated)").arg(selectedNode->GetName().c_str()).toStdString()); + newNode->SetData(output); this->GetDataStorage()->Add(newNode, selectedNode); } void QmitkRemeshingView::EnableWidgets(bool enable) { - m_Controls.densitySlider->setEnabled(enable); - m_Controls.densitySpinBox->setEnabled(enable); - m_Controls.remeshingComboBox->setEnabled(enable); - m_Controls.qualityComboBox->setEnabled(enable); - m_Controls.preserveEdgesCheckBox->setEnabled(enable); - m_Controls.remeshPushButton->setEnabled(enable); - - m_Controls.explanationLabel->setVisible(enable); + m_Controls->polygonCountSlider->setEnabled(enable); + m_Controls->polygonCountSpinBox->setEnabled(enable); + m_Controls->calculateNormalsCheckBox->setEnabled(enable); + m_Controls->flipNormalsCheckBox->setEnabled(enable && m_Controls->calculateNormalsCheckBox->isChecked()); + m_Controls->decimatePushButton->setEnabled(enable); } void QmitkRemeshingView::SetFocus() { - m_Controls.selectionWidget->setFocus(); + m_Controls->selectionWidget->setFocus(); } diff --git a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.h b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.h index 33b384f4d6..679f1679ec 100644 --- a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.h +++ b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingView.h @@ -1,45 +1,49 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ #ifndef QmitkRemeshingView_h #define QmitkRemeshingView_h #include #include -#include + +namespace Ui +{ + class QmitkRemeshingViewControls; +} class QmitkRemeshingView : public QmitkAbstractView { Q_OBJECT public: static const std::string VIEW_ID; QmitkRemeshingView(); ~QmitkRemeshingView() override; void CreateQtPartControl(QWidget* parent) override; void SetFocus() override; private slots: - void OnSelectedSurfaceChanged(const QmitkSingleNodeSelectionWidget::NodeList& nodes); - void OnDensityChanged(int numVertices); - void OnRemeshButtonClicked(); + void OnSurfaceChanged(const QmitkSingleNodeSelectionWidget::NodeList& nodes); + void OnPolygonCountChanged(int polygonCount); + void OnCalculateNormalsChanged(int checkState); + void OnDecimateButtonClicked(); private: void EnableWidgets(bool enable); - Ui::QmitkRemeshingViewControls m_Controls; - int m_MaxNumberOfVertices; + Ui::QmitkRemeshingViewControls* m_Controls; }; #endif diff --git a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingViewControls.ui b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingViewControls.ui index 105b8e2ba4..d06d2ff7fc 100644 --- a/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingViewControls.ui +++ b/Plugins/org.mitk.gui.qt.remeshing/src/internal/QmitkRemeshingViewControls.ui @@ -1,244 +1,172 @@ QmitkRemeshingViewControls true 0 0 253 573 Remeshing 0 0 Surface - - - - - 0 - 40 - + + + + Flip normals - + 0 0 - Density + Polygon count - + 0 0 1 100 10 - 100 + 50 Qt::Horizontal + + + + + 0 + 40 + + + + - + % 1 100 1 - 100 - - - - - - - - 0 - 0 - - - - Remeshing + 50 - - - - Adaptive - - - - - Regular - - - - - - - - - 0 - 0 - - + - Quality - - - - - - - 0 - - - - Medium (fast) - - - - - High (slow) - - - - - Maximum (very slow) - - - - - - - - - 0 - 0 - - - - Preserve Edges + Calculate normals true - + true - Remesh + Decimate :/Remeshing/RemeshingIcon.svg:/Remeshing/RemeshingIcon.svg 24 24 - - - - <html><head/><body><p><span style=" font-weight:600;">Density:</span> The density of the resulting surface compared to the input surface. For example, a density of 50% will effectively halve the number of vertices. It's not uncommen to choose values as low as 10% for overly dense input surfaces. The minimum number of output vertices is at least 100, though.</p><p><span style=" font-weight:600;">Remeshing:</span> Adaptive remeshing results in higher density in curvy areas and less density in flat areas. This remeshing strategy can preserve fine shape details even when the overall density is heavily reduced. Regular remeshing evenly distributes the density regardless of the local shape of the surface.</p><p><span style=" font-weight:600;">Quality</span>: While medium quality is sufficient for the vast majority of use cases, you can increase this setting to further optimize the mesh quality in terms of uniformly shaped triangles. However, computation time and memory consumption increase dramatically compared to very small improvements.</p><p><span style=" font-weight:600;">Preserve Edges:</span> If the input surface contains holes or edges, they will be preserved very accurately by default at the cost of less uniform triangles at their direct neighborhood.</p></body></html> - - - true - - - Qt::Vertical 20 40 QmitkSingleNodeSelectionWidget QWidget
QmitkSingleNodeSelectionWidget.h
1
- densitySpinBox - preserveEdgesCheckBox - remeshPushButton + polygonCountSpinBox + decimatePushButton
diff --git a/Plugins/org.mitk.gui.qt.remeshing/target_libraries.cmake b/Plugins/org.mitk.gui.qt.remeshing/target_libraries.cmake deleted file mode 100644 index 6c71bbbf08..0000000000 --- a/Plugins/org.mitk.gui.qt.remeshing/target_libraries.cmake +++ /dev/null @@ -1,3 +0,0 @@ -set(target_libraries - CTKWidgets -) diff --git a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp index 698f380ad3..33520df2fe 100644 --- a/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp +++ b/Plugins/org.mitk.gui.qt.tofutil/src/internal/QmitkToFUtilView.cpp @@ -1,526 +1,526 @@ /*============================================================================ The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center (DKFZ) All rights reserved. Use of this source code is governed by a 3-clause BSD license that can be found in the LICENSE file. ============================================================================*/ // Blueberry #include #include #include // Qmitk #include "QmitkToFUtilView.h" // Qt #include #include #include #include #include // MITK #include #include #include #include #include #include #include #include #include #include // VTK #include #include #include // ITK #include #include const std::string QmitkToFUtilView::VIEW_ID = "org.mitk.views.tofutil"; //Constructor QmitkToFUtilView::QmitkToFUtilView() : QmitkAbstractView() , m_Controls(nullptr) , m_Framerateoutput(false) , m_MitkDistanceImage(nullptr), m_MitkAmplitudeImage(nullptr), m_MitkIntensityImage(nullptr), m_Surface(nullptr) , m_DistanceImageNode(nullptr), m_AmplitudeImageNode(nullptr), m_IntensityImageNode(nullptr), m_RGBImageNode(nullptr), m_SurfaceNode(nullptr) , m_ToFImageRecorder(nullptr), m_ToFImageGrabber(nullptr), m_ToFDistanceImageToSurfaceFilter(nullptr), m_ToFCompositeFilter(nullptr) , m_2DDisplayCount(0) , m_RealTimeClock(nullptr) , m_StepsForFramerate(100) , m_2DTimeBefore(0.0) , m_2DTimeAfter(0.0) , m_CameraIntrinsics(nullptr) { this->m_Frametimer = new QTimer(this); this->m_ToFDistanceImageToSurfaceFilter = mitk::ToFDistanceImageToSurfaceFilter::New(); this->m_ToFCompositeFilter = mitk::ToFCompositeFilter::New(); this->m_ToFImageRecorder = mitk::ToFImageRecorder::New(); } //Destructor, specifically calling OnToFCameraStopped() and OnToFCammeraDiconnected() QmitkToFUtilView::~QmitkToFUtilView() { OnToFCameraStopped(); OnToFCameraDisconnected(); } //Createing the PartControl Signal-Slot principal void QmitkToFUtilView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkToFUtilViewControls; m_Controls->setupUi( parent ); //Looking for Input and Defining reaction connect(m_Frametimer, SIGNAL(timeout()), this, SLOT(OnUpdateCamera())); connect( (QObject*)(m_Controls->m_ToFConnectionWidget), SIGNAL(KinectAcquisitionModeChanged()), this, SLOT(OnKinectAcquisitionModeChanged()) ); // Todo in Widget2 connect( (QObject*)(m_Controls->m_ToFConnectionWidget), SIGNAL(ToFCameraConnected()), this, SLOT(OnToFCameraConnected()) ); connect( (QObject*)(m_Controls->m_ToFConnectionWidget), SIGNAL(ToFCameraDisconnected()), this, SLOT(OnToFCameraDisconnected()) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(ToFCameraStarted()), this, SLOT(OnToFCameraStarted()) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(ToFCameraStopped()), this, SLOT(OnToFCameraStopped()) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(RecordingStarted()), this, SLOT(OnToFCameraStopped()) ); connect( (QObject*)(m_Controls->m_ToFRecorderWidget), SIGNAL(RecordingStopped()), this, SLOT(OnToFCameraStarted()) ); } } //SetFocus-Method -> actually seting Focus to the Recorder void QmitkToFUtilView::SetFocus() { m_Controls->m_ToFRecorderWidget->setFocus(); } //Activated-Method->Generating RenderWindow void QmitkToFUtilView::Activated() { //get the current RenderWindowPart or open a new one if there is none if (this->GetRenderWindowPart(mitk::WorkbenchUtil::IRenderWindowPartStrategy::OPEN)) { mitk::ILinkedRenderWindowPart* linkedRenderWindowPart = dynamic_cast(this->GetRenderWindowPart()); if (linkedRenderWindowPart == nullptr) { MITK_ERROR << "No linked render window part avaiable!!!"; } else { linkedRenderWindowPart->EnableSlicingPlanes(false); } GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SliceLockedOn(); GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()->SliceLockedOn(); GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()->SliceLockedOn(); mitk::RenderingManager::GetInstance()->InitializeViews(); this->UseToFVisibilitySettings(true); if (this->m_ToFCompositeFilter) { m_Controls->m_ToFCompositeFilterWidget->SetToFCompositeFilter(this->m_ToFCompositeFilter); } if (this->GetDataStorage()) { m_Controls->m_ToFCompositeFilterWidget->SetDataStorage(this->GetDataStorage()); } if (this->m_ToFImageGrabber.IsNull()) { m_Controls->m_ToFRecorderWidget->setEnabled(false); m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(false); m_Controls->m_ToFCompositeFilterWidget->setEnabled(false); m_Controls->m_ToFMeasurementWidget->setEnabled(false); m_Controls->m_ToFSurfaceGenerationWidget->setEnabled(false); } } } //ZomnnieView-Method -> Resetting GUI to default. Why not just QmitkToFUtilView()?! void QmitkToFUtilView::ActivatedZombieView(berry::IWorkbenchPartReference::Pointer /*zombieView*/) { ResetGUIToDefault(); } void QmitkToFUtilView::Deactivated() { } void QmitkToFUtilView::Visible() { } //Reset of the ToFUtilView void QmitkToFUtilView::Hidden() { ResetGUIToDefault(); } void QmitkToFUtilView::OnToFCameraConnected() { MITK_DEBUG <<"OnToFCameraConnected"; this->m_2DDisplayCount = 0; this->m_ToFImageGrabber = m_Controls->m_ToFConnectionWidget->GetToFImageGrabber(); // initialize surface generation this->m_ToFDistanceImageToSurfaceFilter = mitk::ToFDistanceImageToSurfaceFilter::New(); // initialize ToFImageRecorder and ToFRecorderWidget this->m_ToFImageRecorder = mitk::ToFImageRecorder::New(); this->m_ToFImageRecorder->SetCameraDevice(this->m_ToFImageGrabber->GetCameraDevice()); m_Controls->m_ToFRecorderWidget->SetParameter(this->m_ToFImageGrabber, this->m_ToFImageRecorder); m_Controls->m_ToFRecorderWidget->setEnabled(true); m_Controls->m_ToFRecorderWidget->ResetGUIToInitial(); m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(false); // initialize ToFCompositeFilterWidget this->m_ToFCompositeFilter = mitk::ToFCompositeFilter::New(); if (this->m_ToFCompositeFilter) { m_Controls->m_ToFCompositeFilterWidget->SetToFCompositeFilter(this->m_ToFCompositeFilter); } if (this->GetDataStorage()) { m_Controls->m_ToFCompositeFilterWidget->SetDataStorage(this->GetDataStorage()); } if ( this->GetRenderWindowPart() ) // initialize measurement widget m_Controls->m_ToFMeasurementWidget->InitializeWidget(this->GetRenderWindowPart()->GetQmitkRenderWindows(),this->GetDataStorage(), this->m_ToFDistanceImageToSurfaceFilter->GetCameraIntrinsics()); else MITK_WARN << "No render window part available!!! MeasurementWidget will not work."; this->m_RealTimeClock = mitk::RealTimeClock::New(); this->m_2DTimeBefore = this->m_RealTimeClock->GetCurrentStamp(); this->RequestRenderWindowUpdate(); } void QmitkToFUtilView::ResetGUIToDefault() { if(this->GetRenderWindowPart()) { mitk::ILinkedRenderWindowPart* linkedRenderWindowPart = dynamic_cast(this->GetRenderWindowPart()); if(linkedRenderWindowPart == nullptr) { MITK_ERROR << "No linked render window part avaiable!!!"; } else { linkedRenderWindowPart->EnableSlicingPlanes(true); } GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetSliceNavigationController()->SliceLockedOff(); GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Sagittal); GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetSliceNavigationController()->SliceLockedOff(); GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Frontal); GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetSliceNavigationController()->SliceLockedOff(); this->UseToFVisibilitySettings(false); //global reinit mitk::RenderingManager::GetInstance()->InitializeViews(); this->RequestRenderWindowUpdate(); } } void QmitkToFUtilView::OnToFCameraDisconnected() { this->GetDataStorage()->Remove(m_DistanceImageNode); if(m_RGBImageNode) this->GetDataStorage()->Remove(m_RGBImageNode); if(m_AmplitudeImageNode) this->GetDataStorage()->Remove(m_AmplitudeImageNode); if(m_IntensityImageNode) this->GetDataStorage()->Remove(m_IntensityImageNode); if(m_SurfaceNode) this->GetDataStorage()->Remove(m_SurfaceNode); m_Controls->m_ToFRecorderWidget->OnStop(); m_Controls->m_ToFRecorderWidget->setEnabled(false); m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(false); m_Controls->m_ToFMeasurementWidget->setEnabled(false); m_Controls->m_ToFSurfaceGenerationWidget->setEnabled(false); //clean up measurement widget m_Controls->m_ToFMeasurementWidget->CleanUpWidget(); } void QmitkToFUtilView::OnKinectAcquisitionModeChanged() { if (m_ToFCompositeFilter.IsNotNull()&&m_ToFImageGrabber.IsNotNull()) { if (m_SelectedCamera.contains("Kinect")) { if (m_ToFImageGrabber->GetBoolProperty("RGB")) { this->m_RGBImageNode = ReplaceNodeData("RGB image",this->m_ToFImageGrabber->GetOutput(3)); this->m_ToFDistanceImageToSurfaceFilter->SetInput(3,this->m_ToFImageGrabber->GetOutput(3)); } else if (m_ToFImageGrabber->GetBoolProperty("IR")) { this->m_MitkAmplitudeImage = m_ToFCompositeFilter->GetOutput(1); this->m_AmplitudeImageNode = ReplaceNodeData("Amplitude image",m_MitkAmplitudeImage); } } this->UseToFVisibilitySettings(true); } } void QmitkToFUtilView::OnToFCameraStarted() { if (m_ToFImageGrabber.IsNotNull()) { // initialize camera intrinsics if (this->m_ToFImageGrabber->GetProperty("CameraIntrinsics")) { m_CameraIntrinsics = dynamic_cast(this->m_ToFImageGrabber->GetProperty("CameraIntrinsics"))->GetValue(); MITK_INFO << m_CameraIntrinsics->ToString(); } else { m_CameraIntrinsics = nullptr; MITK_ERROR << "No camera intrinsics were found!"; } // set camera intrinsics if ( m_CameraIntrinsics.IsNotNull() ) { this->m_ToFDistanceImageToSurfaceFilter->SetCameraIntrinsics(m_CameraIntrinsics); } // initial update of image grabber this->m_ToFImageGrabber->Update(); bool hasRGBImage = false; m_ToFImageGrabber->GetCameraDevice()->GetBoolProperty("HasRGBImage",hasRGBImage); bool hasIntensityImage = false; m_ToFImageGrabber->GetCameraDevice()->GetBoolProperty("HasIntensityImage",hasIntensityImage); bool hasAmplitudeImage = false; m_ToFImageGrabber->GetCameraDevice()->GetBoolProperty("HasAmplitudeImage",hasAmplitudeImage); this->m_ToFCompositeFilter->SetInput(0,this->m_ToFImageGrabber->GetOutput(0)); if(hasAmplitudeImage) this->m_ToFCompositeFilter->SetInput(1,this->m_ToFImageGrabber->GetOutput(1)); if(hasIntensityImage) this->m_ToFCompositeFilter->SetInput(2,this->m_ToFImageGrabber->GetOutput(2)); // initial update of composite filter this->m_ToFCompositeFilter->Update(); this->m_MitkDistanceImage = m_ToFCompositeFilter->GetOutput(); this->m_DistanceImageNode = ReplaceNodeData("Distance image",m_MitkDistanceImage); std::string rgbFileName; m_ToFImageGrabber->GetCameraDevice()->GetStringProperty("RGBImageFileName",rgbFileName); if(hasRGBImage || (rgbFileName!="")) { if(m_ToFImageGrabber->GetBoolProperty("IR")) { this->m_MitkAmplitudeImage = m_ToFCompositeFilter->GetOutput(1); } else { this->m_RGBImageNode = ReplaceNodeData("RGB image",this->m_ToFImageGrabber->GetOutput(3)); } } else { this->m_RGBImageNode = nullptr; } if(hasAmplitudeImage) { this->m_MitkAmplitudeImage = m_ToFCompositeFilter->GetOutput(1); this->m_AmplitudeImageNode = ReplaceNodeData("Amplitude image",m_MitkAmplitudeImage); } if(hasIntensityImage) { this->m_MitkIntensityImage = m_ToFCompositeFilter->GetOutput(2); this->m_IntensityImageNode = ReplaceNodeData("Intensity image",m_MitkIntensityImage); } this->m_ToFDistanceImageToSurfaceFilter->SetInput(0,m_MitkDistanceImage); this->m_ToFDistanceImageToSurfaceFilter->SetInput(1,m_MitkAmplitudeImage); this->m_ToFDistanceImageToSurfaceFilter->SetInput(2,m_MitkIntensityImage); this->UseToFVisibilitySettings(true); this->m_SurfaceNode = ReplaceNodeData("Surface", nullptr); m_Controls->m_ToFCompositeFilterWidget->UpdateFilterParameter(); // initialize visualization widget m_Controls->m_ToFVisualisationSettingsWidget->Initialize(this->m_DistanceImageNode, this->m_AmplitudeImageNode, this->m_IntensityImageNode, this->m_SurfaceNode); m_Controls->m_ToFSurfaceGenerationWidget->Initialize(m_ToFDistanceImageToSurfaceFilter, m_ToFImageGrabber, m_CameraIntrinsics, m_SurfaceNode, GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderer()->GetVtkRenderer()->GetActiveCamera()); // set distance image to measurement widget m_Controls->m_ToFMeasurementWidget->SetDistanceImage(m_MitkDistanceImage); this->m_Frametimer->start(50); m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(true); m_Controls->m_ToFCompositeFilterWidget->setEnabled(true); m_Controls->m_ToFMeasurementWidget->setEnabled(true); m_Controls->m_ToFSurfaceGenerationWidget->setEnabled(true); } } void QmitkToFUtilView::OnToFCameraStopped() { m_Controls->m_ToFVisualisationSettingsWidget->setEnabled(false); m_Controls->m_ToFCompositeFilterWidget->setEnabled(false); this->m_Frametimer->stop(); } void QmitkToFUtilView::OnUpdateCamera() { if(!m_Controls->m_ToFSurfaceGenerationWidget->UpdateSurface()) { // update pipeline this->m_MitkDistanceImage->Update(); } this->RequestRenderWindowUpdate(); if (m_Framerateoutput) { this->m_2DDisplayCount++; if ((this->m_2DDisplayCount % this->m_StepsForFramerate) == 0) { this->m_2DTimeAfter = this->m_RealTimeClock->GetCurrentStamp() - this->m_2DTimeBefore; MITK_INFO << " 2D-Display-framerate (fps): " << this->m_StepsForFramerate / (this->m_2DTimeAfter / 1000); this->m_2DTimeBefore = this->m_RealTimeClock->GetCurrentStamp(); } } } void QmitkToFUtilView::OnChangeCoronalWindowOutput(int index) { this->OnToFCameraStopped(); if(index == 0) { if(this->m_IntensityImageNode.IsNotNull()) this->m_IntensityImageNode->SetVisibility(false); if(this->m_RGBImageNode.IsNotNull()) this->m_RGBImageNode->SetVisibility(true); } else if(index == 1) { if(this->m_IntensityImageNode.IsNotNull()) this->m_IntensityImageNode->SetVisibility(true); if(this->m_RGBImageNode.IsNotNull()) this->m_RGBImageNode->SetVisibility(false); } this->RequestRenderWindowUpdate(); this->OnToFCameraStarted(); } mitk::DataNode::Pointer QmitkToFUtilView::ReplaceNodeData( std::string nodeName, mitk::BaseData* data ) { mitk::DataNode::Pointer node = this->GetDataStorage()->GetNamedNode(nodeName); if (node.IsNull()) { node = mitk::DataNode::New(); node->SetName(nodeName); node->SetBoolProperty("binary",false); node->SetData(data); this->GetDataStorage()->Add(node); } else { node->SetData(data); } return node; } void QmitkToFUtilView::UseToFVisibilitySettings(bool useToF) { //We need this property for every node. mitk::RenderingModeProperty::Pointer renderingModePropertyForTransferFunction = mitk::RenderingModeProperty::New(mitk::RenderingModeProperty::COLORTRANSFERFUNCTION_COLOR); // set node properties if (m_DistanceImageNode.IsNotNull()) { this->m_DistanceImageNode->SetProperty( "visible" , mitk::BoolProperty::New( true )); - this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetRenderWindow() ) ); - this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetRenderWindow() ) ); - this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderWindow() ) ); + this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->renderWindow() ) ); + this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->renderWindow() ) ); + this->m_DistanceImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->renderWindow() ) ); this->m_DistanceImageNode->SetProperty("Image Rendering.Mode", renderingModePropertyForTransferFunction); } if (m_AmplitudeImageNode.IsNotNull()) { - this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetRenderWindow() ) ); - this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetRenderWindow() ) ); - this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderWindow() ) ); + this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("axial")->renderWindow() ) ); + this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->renderWindow() ) ); + this->m_AmplitudeImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->renderWindow() ) ); this->m_AmplitudeImageNode->SetProperty("Image Rendering.Mode", renderingModePropertyForTransferFunction); } if (m_IntensityImageNode.IsNotNull()) { this->m_IntensityImageNode->SetProperty( "visible" , mitk::BoolProperty::New( true )); - this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetRenderWindow() ) ); - this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetRenderWindow() ) ); - this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderWindow() ) ); + this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("axial")->renderWindow() ) ); + this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->renderWindow() ) ); + this->m_IntensityImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->renderWindow() ) ); this->m_IntensityImageNode->SetProperty("Image Rendering.Mode", renderingModePropertyForTransferFunction); } if ((m_RGBImageNode.IsNotNull())) { this->m_RGBImageNode->SetProperty( "visible" , mitk::BoolProperty::New( true )); - this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("axial")->GetRenderWindow() ) ); - this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->GetRenderWindow() ) ); - this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderWindow() ) ); + this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("axial")->renderWindow() ) ); + this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("sagittal")->renderWindow() ) ); + this->m_RGBImageNode->SetVisibility( !useToF, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->renderWindow() ) ); } // initialize images if (m_MitkDistanceImage.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( this->m_MitkDistanceImage->GetTimeGeometry(), mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS, true); } if(this->m_SurfaceNode.IsNotNull()) { QHash renderWindowHashMap = this->GetRenderWindowPart()->GetQmitkRenderWindows(); QHashIterator i(renderWindowHashMap); while (i.hasNext()){ i.next(); - this->m_SurfaceNode->SetVisibility( false, mitk::BaseRenderer::GetInstance(i.value()->GetRenderWindow()) ); + this->m_SurfaceNode->SetVisibility( false, mitk::BaseRenderer::GetInstance(i.value()->renderWindow()) ); } - this->m_SurfaceNode->SetVisibility( true, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->GetRenderWindow() ) ); + this->m_SurfaceNode->SetVisibility( true, mitk::BaseRenderer::GetInstance(GetRenderWindowPart()->GetQmitkRenderWindow("3d")->renderWindow() ) ); } //disable/enable gradient background this->GetRenderWindowPart()->EnableDecorations(!useToF, QStringList(QString("background"))); if((this->m_RGBImageNode.IsNotNull())) { bool RGBImageHasDifferentResolution = false; m_ToFImageGrabber->GetCameraDevice()->GetBoolProperty("RGBImageHasDifferentResolution",RGBImageHasDifferentResolution); if(RGBImageHasDifferentResolution) { //update the display geometry by using the RBG image node. Only for renderwindow coronal - mitk::RenderingManager::GetInstance()->InitializeView( GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->GetRenderWindow(), this->m_RGBImageNode->GetData()->GetGeometry() ); + mitk::RenderingManager::GetInstance()->InitializeView( GetRenderWindowPart()->GetQmitkRenderWindow("coronal")->renderWindow(), this->m_RGBImageNode->GetData()->GetGeometry() ); } } }