diff --git a/.gitattributes b/.gitattributes index b3de23e58d..51a00f8038 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,65 +1,68 @@ .git* export-ignore .hooks* export-ignore .mailmap export-ignore # Set general file size limit on all files * hooks.MaxObjectKiB=1024 *.bat -crlf *.bin -crlf *.blend -crlf *.bmp -crlf *.cpt -crlf *.gif -crlf *.icns -crlf *.ico -crlf *.jpeg -crlf *.jpg -crlf *.mha -crlf *.odg -crlf *.pbxproj -crlf *.pdf -crlf *.plist -crlf *.png -crlf *.ppt -crlf *.pptx -crlf *.raw -crlf *.vtk -crlf *.xcf -crlf *.xpm -crlf -diff *.sh crlf=input *.sh.in crlf=input configure crlf=input cvsrmvend crlf=input imcp crlf=input imglob crlf=input imln crlf=input immv crlf=input imrm crlf=input imtest crlf=input install-sh crlf=input newalpha crlf=input newversion crlf=input remove_ext crlf=input vxl_doxy.pl crlf=input zap.pl crlf=input *.c whitespace=tab-in-indent,no-lf-at-eof copyright=mitk-license hooks.style=KWStyle,uncrustify *.cpp whitespace=tab-in-indent,no-lf-at-eof copyright=mitk-license hooks.style=KWStyle,uncrustify *.h whitespace=tab-in-indent,no-lf-at-eof copyright=mitk-license hooks.style=KWStyle,uncrustify *.cxx whitespace=tab-in-indent,no-lf-at-eof copyright=mitk-license hooks.style=KWStyle,uncrustify *.hxx whitespace=tab-in-indent,no-lf-at-eof copyright=mitk-license hooks.style=KWStyle,uncrustify *.txx whitespace=tab-in-indent,no-lf-at-eof copyright=mitk-license hooks.style=KWStyle,uncrustify *.txt whitespace=tab-in-indent,no-lf-at-eof *.cmake whitespace=tab-in-indent,no-lf-at-eof # The Microservices use an apache copyright Core/Code/CppMicroServices/**/*.c copyright=apache-license Core/Code/CppMicroServices/**/*.cpp copyright=apache-license Core/Code/CppMicroServices/**/*.h copyright=apache-license # There is no need to check files in the utilities directory for copyright Utilities/** -copyright +Applications/PluginGenerator/PluginTemplate/src/**/*.h -copyright +Applications/PluginGenerator/PluginTemplate/src/**/*.cpp -copyright +Applications/PluginGenerator/ProjectTemplate/Apps/TemplateApp/TemplateApp.cpp -copyright # ExternalData content links must have LF newlines *.md5 crlf=input diff --git a/Applications/PluginGenerator/LICENSE.txt b/Applications/PluginGenerator/LICENSE.txt index 8761edc246..07c13ca843 100644 --- a/Applications/PluginGenerator/LICENSE.txt +++ b/Applications/PluginGenerator/LICENSE.txt @@ -1,29 +1,29 @@ Copyright (c) 2003-2012 German Cancer Research Center, Division of Medical and Biological Informatics All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of the German Cancer Research Center, nor the names of - its contributors may be used to endorse or promote products derived from + * Neither the name of the German Cancer Research Center, nor the names of + its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/Manual.dox b/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/Manual.dox index c254a2ba83..56feaaae05 100755 --- a/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/Manual.dox +++ b/Applications/PluginGenerator/PluginTemplate/documentation/UserManual/Manual.dox @@ -1,19 +1,18 @@ /** \page $(plugin-target) $(plugin-name) \image html icon.xpm "Icon of $(plugin-name)" Available sections: - \ref $(plugin-target)Overview \section $(plugin-target)Overview Describe the features of your awesome plugin here */ - diff --git a/Applications/PluginGenerator/PluginTemplate/documentation/doxygen/modules.dox b/Applications/PluginGenerator/PluginTemplate/documentation/doxygen/modules.dox index 4a1244f9a8..9dcb60e028 100644 --- a/Applications/PluginGenerator/PluginTemplate/documentation/doxygen/modules.dox +++ b/Applications/PluginGenerator/PluginTemplate/documentation/doxygen/modules.dox @@ -1,16 +1,16 @@ /** \defgroup $(plugin-target) $(plugin-symbolic-name) \ingroup MITKPlugins \brief Describe your plugin here. - + */ /** \defgroup $(plugin-target)_internal Internal \ingroup $(plugin-target) \brief This subcategory includes the internal classes of the $(plugin-symbolic-name) plugin. Other plugins must not rely on these classes. They contain implementation details and their interface may change at any time. We mean it. */ diff --git a/Applications/PluginGenerator/PluginTemplate/files.cmake b/Applications/PluginGenerator/PluginTemplate/files.cmake index ad0fe7df61..c1b3369574 100644 --- a/Applications/PluginGenerator/PluginTemplate/files.cmake +++ b/Applications/PluginGenerator/PluginTemplate/files.cmake @@ -1,43 +1,42 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES $(activator-file-name).cpp $(view-file-name).cpp ) set(UI_FILES src/internal/$(view-file-name)Controls.ui ) set(MOC_H_FILES src/internal/$(activator-file-name).h src/internal/$(view-file-name).h ) # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench set(CACHED_RESOURCE_FILES resources/icon.xpm plugin.xml ) # list of Qt .qrc files which contain additional resources # specific to this plugin set(QRC_FILES ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) - diff --git a/Applications/PluginGenerator/PluginTemplate/plugin.xml b/Applications/PluginGenerator/PluginTemplate/plugin.xml index 51215b975c..edacef0b6f 100644 --- a/Applications/PluginGenerator/PluginTemplate/plugin.xml +++ b/Applications/PluginGenerator/PluginTemplate/plugin.xml @@ -1,11 +1,11 @@ - + diff --git a/Applications/PluginGenerator/PluginTemplate/src/internal/QmitkTemplateView.h b/Applications/PluginGenerator/PluginTemplate/src/internal/QmitkTemplateView.h index 40ffd7bac8..73d8c90fde 100644 --- a/Applications/PluginGenerator/PluginTemplate/src/internal/QmitkTemplateView.h +++ b/Applications/PluginGenerator/PluginTemplate/src/internal/QmitkTemplateView.h @@ -1,51 +1,50 @@ $(license) #ifndef $(view-file-name)_h #define $(view-file-name)_h #include #include #include "ui_$(view-file-name)Controls.h" -/*! +/** \brief $(view-class-name) \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. - \sa QmitkFunctionality + \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ class $(view-class-name) : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; - virtual void CreateQtPartControl(QWidget *parent); - protected slots: /// \brief Called when the user clicks the GUI button void DoImageProcessing(); protected: + virtual void CreateQtPartControl(QWidget *parent); + virtual void SetFocus(); /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, const QList& nodes ); Ui::$(view-file-name)Controls m_Controls; }; #endif // $(view-file-name)_h - diff --git a/BlueBerry/Bundles/org.blueberry.compat/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.compat/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..144ea564d0 --- /dev/null +++ b/BlueBerry/Bundles/org.blueberry.compat/documentation/doxygen/modules.dox @@ -0,0 +1,18 @@ +/** + \defgroup org_blueberry_compat org.blueberry.compat + \ingroup BlueBerryPlugins + + \brief Track CTK plug-ins and register their extensions and extension-points. + + This plug-in listens to CTK plug-in events and populates the BlueBerry extension + registry with entries from the plug-ins embedded plugin.xml files. +*/ + +/** + \defgroup org_blueberry_compat_internal Internal + \ingroup org_blueberry_compat + + \brief This subcategory includes the internal classes of the org.blueberry.compat plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/BlueBerry/Bundles/org.blueberry.core.commands/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.core.commands/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..736f33263a --- /dev/null +++ b/BlueBerry/Bundles/org.blueberry.core.commands/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_blueberry_core_commands org.blueberry.core.commands + \ingroup BlueBerryPlugins + + \brief Provides an infrastructure for executing commands in the Workbench. + +*/ + +/** + \defgroup org_blueberry_core_commands_internal Internal + \ingroup org_blueberry_core_commands + + \brief This subcategory includes the internal classes of the org.blueberry.core.commands plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/BlueBerry/Bundles/org.blueberry.core.expressions/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.core.expressions/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..000328274f --- /dev/null +++ b/BlueBerry/Bundles/org.blueberry.core.expressions/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_blueberry_core_expressions org.blueberry.core.expressions + \ingroup BlueBerryPlugins + + \brief Evaluates complex expressions defined in XML. + +*/ + +/** + \defgroup org_blueberry_core_expressions_internal Internal + \ingroup org_blueberry_core_expressions + + \brief This subcategory includes the internal classes of the org.blueberry.core.expressions plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/BlueBerry/Bundles/org.blueberry.core.jobs/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.core.jobs/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..176b176704 --- /dev/null +++ b/BlueBerry/Bundles/org.blueberry.core.jobs/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_blueberry_core_jobs org.blueberry.core.jobs + \ingroup BlueBerryPlugins + + \brief A generic jobs API for running background tasks in a BlueBerry application. + +*/ + +/** + \defgroup org_blueberry_core_jobs_internal Internal + \ingroup org_blueberry_core_jobs + + \brief This subcategory includes the internal classes of the org.blueberry.core.jobs plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/BlueBerry/Bundles/org.blueberry.core.runtime/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.core.runtime/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..5508603d74 --- /dev/null +++ b/BlueBerry/Bundles/org.blueberry.core.runtime/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_blueberry_core_runtime org.blueberry.core.runtime + \ingroup BlueBerryPlugins + + \brief Provides runtime services like preferences. + +*/ + +/** + \defgroup org_blueberry_core_runtime_internal Internal + \ingroup org_blueberry_core_runtime + + \brief This subcategory includes the internal classes of the org.blueberry.core.runtime plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/BlueBerry/Bundles/org.blueberry.osgi/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.osgi/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..da7c1015aa --- /dev/null +++ b/BlueBerry/Bundles/org.blueberry.osgi/documentation/doxygen/modules.dox @@ -0,0 +1,18 @@ +/** + \defgroup org_blueberry_osgi org.blueberry.osgi + \ingroup BlueBerryPlugins + + \brief The partial BlueBerry OSGi implementation. + + Most of the functionality of this plug-in has been superseded by the CTK Plugin Framework + and is only kept for backwards compatibility. +*/ + +/** + \defgroup org_blueberry_osgi_internal Internal + \ingroup org_blueberry_osgi + + \brief This subcategory includes the internal classes of the org.blueberry.osgi plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/BlueBerry/Bundles/org.blueberry.solstice.common/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.solstice.common/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..913ef08927 --- /dev/null +++ b/BlueBerry/Bundles/org.blueberry.solstice.common/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_blueberry_solstice_common org.blueberry.solstice.common + \ingroup BlueBerryPlugins + + \brief Provides common functionality like status handling of method calls. + +*/ + +/** + \defgroup org_blueberry_solstice_common_internal Internal + \ingroup org_blueberry_solstice_common + + \brief This subcategory includes the internal classes of the org.blueberry.solstice.common plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/BlueBerry/Bundles/org.blueberry.test/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.test/documentation/doxygen/modules.dox index 15d1afa735..f15b97ba2a 100644 --- a/BlueBerry/Bundles/org.blueberry.test/documentation/doxygen/modules.dox +++ b/BlueBerry/Bundles/org.blueberry.test/documentation/doxygen/modules.dox @@ -1,16 +1,16 @@ /** \defgroup org_blueberry_test org.blueberry.test \ingroup BlueBerryPlugins - \brief Describe your plugin here. + \brief Testing infrastructure for running unit tests defined in BlueBerry plug-ins. */ /** \defgroup org_blueberry_test_internal Internal \ingroup org_blueberry_test \brief This subcategory includes the internal classes of the org.blueberry.test plugin. Other plugins must not rely on these classes. They contain implementation details and their interface may change at any time. We mean it. */ diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt.log/documentation/UserManual/blueberrylogview.dox b/BlueBerry/Bundles/org.blueberry.ui.qt.log/documentation/UserManual/blueberrylogview.dox index dbde26a7f5..92453eb6f4 100644 --- a/BlueBerry/Bundles/org.blueberry.ui.qt.log/documentation/UserManual/blueberrylogview.dox +++ b/BlueBerry/Bundles/org.blueberry.ui.qt.log/documentation/UserManual/blueberrylogview.dox @@ -1,16 +1,16 @@ /** -\page org_blueberry_ui_qt_log The Logging Module +\page org_blueberry_ui_qt_log The Logging Plugin \image html Logging.png "Icon of the Module" -The Plug-In "Logging Module" records all logging output of events and progress as specified in the source code with time of occurence, level of importance (Info, Warning, Error, Fatal, Debug), the message given and where it happens. The logging starts once you activate the Plug-In in your main application. A screenshot of the main view of the Logging Module is shown next. +This plug-in records all logging output of events and progress as specified in the source code with time of occurence, level of importance (Info, Warning, Error, Fatal, Debug), the message given and where it happens. The logging starts once the plug-is started. A screenshot of the provided Logging view is shown next. \image html LogView.png "Screenshot of the Logging Module" There are different features available in the view. The filter text field allows for searching all log events containing a certain substring. Using the button "Copy to clipboard" on the bottom right you can copy the current content of the logging view to your clipboard. This enables you to insert the logging information to any text processing application. You can also show more information on every logging message by activating the two checkboxes. In the simple view, leaving both checkboxes unchecked, you'll see logging messages and logging levels. A brief description of the logging levels can be found in the \ref LoggingPage "logging concept documentation". The checkbox "Category" adds a column for the category. The checkbox "Show Advanced Field" shows method, filename and linenumber where the logging message was emitted as well as the running time of the application. The next figure shows all information which can be shown in the Logging Module. \image html LogViewExplain.png "Details on the Vizualized Logging Information" -*/ \ No newline at end of file +*/ diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt.log/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.ui.qt.log/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..6a7ace0f6b --- /dev/null +++ b/BlueBerry/Bundles/org.blueberry.ui.qt.log/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_blueberry_ui_qt_log org.blueberry.ui.qt.log + \ingroup BlueBerryPlugins + + \brief Provides a Logging View for BlueBerry applications. + +*/ + +/** + \defgroup org_blueberry_ui_qt_log_internal Internal + \ingroup org_blueberry_ui_qt_log + + \brief This subcategory includes the internal classes of the org.blueberry.ui.qt.log plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/documentation/doxygen/modules.dox index 9a37cee3c1..b54679971a 100644 --- a/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/documentation/doxygen/modules.dox +++ b/BlueBerry/Bundles/org.blueberry.ui.qt.objectinspector/documentation/doxygen/modules.dox @@ -1,16 +1,17 @@ /** \defgroup org_blueberry_ui_qt_objectinspector org.blueberry.ui.qt.objectinspector \ingroup BlueBerryPlugins - \brief Describe your plugin here. + \brief A debugging plug-in providing a BlueBerry View for inspecting berry::Object + instances and their associated smart-pointers. */ /** \defgroup org_blueberry_ui_qt_objectinspector_internal Internal \ingroup org_blueberry_ui_qt_objectinspector \brief This subcategory includes the internal classes of the org.blueberry.ui.qt.objectinspector plugin. Other plugins must not rely on these classes. They contain implementation details and their interface may change at any time. We mean it. */ diff --git a/BlueBerry/Bundles/org.blueberry.ui.qt/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.ui.qt/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..a45832401a --- /dev/null +++ b/BlueBerry/Bundles/org.blueberry.ui.qt/documentation/doxygen/modules.dox @@ -0,0 +1,17 @@ +/** + \defgroup org_blueberry_ui_qt org.blueberry.ui.qt + \ingroup BlueBerryPlugins + + \brief The Qt dependent user interface plug-in providing support for + creating Qt based workbench applications. + +*/ + +/** + \defgroup org_blueberry_ui_qt_internal Internal + \ingroup org_blueberry_ui_qt + + \brief This subcategory includes the internal classes of the org.blueberry.ui.qt plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/BlueBerry/Bundles/org.blueberry.ui/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.ui/documentation/doxygen/modules.dox index 8c3525ed7b..65d01619f0 100644 --- a/BlueBerry/Bundles/org.blueberry.ui/documentation/doxygen/modules.dox +++ b/BlueBerry/Bundles/org.blueberry.ui/documentation/doxygen/modules.dox @@ -1,17 +1,17 @@ /** \defgroup org_blueberry_ui org.blueberry.ui \ingroup BlueBerryPlugins \brief This is the user interface plugin. It provides a GUI-Toolkit independent framework - to build an BlueBerry workbench. + to build a BlueBerry workbench. */ /** \defgroup org_blueberry_ui_internal Internal \ingroup org_blueberry_ui \brief This subcategory includes the internal classes of the org.blueberry.ui plugin. Other plugins must not rely on these classes. They contain implementation details and their interface may change at any time. We mean it. -*/ \ No newline at end of file +*/ diff --git a/BlueBerry/Bundles/org.blueberry.uitest/documentation/doxygen/modules.dox b/BlueBerry/Bundles/org.blueberry.uitest/documentation/doxygen/modules.dox index 599c765dc4..95c905fe9d 100644 --- a/BlueBerry/Bundles/org.blueberry.uitest/documentation/doxygen/modules.dox +++ b/BlueBerry/Bundles/org.blueberry.uitest/documentation/doxygen/modules.dox @@ -1,16 +1,16 @@ /** \defgroup org_blueberry_uitest org.blueberry.uitest \ingroup BlueBerryPlugins - \brief Describe your plugin here. + \brief Testing infrastructure for executing unit tests which require a running workbench. */ /** \defgroup org_blueberry_uitest_internal Internal \ingroup org_blueberry_uitest \brief This subcategory includes the internal classes of the org.blueberry.uitest plugin. Other plugins must not rely on these classes. They contain implementation details and their interface may change at any time. We mean it. */ diff --git a/BlueBerry/Documentation/CMakeLists.txt b/BlueBerry/Documentation/CMakeLists.txt index 3114734fc9..e3886382b1 100755 --- a/BlueBerry/Documentation/CMakeLists.txt +++ b/BlueBerry/Documentation/CMakeLists.txt @@ -1,86 +1,91 @@ -# +# # Variables: # BLUEBERRY_DOCS_OUTPUT_DIR: documentation output directory (optional) add_subdirectory(snippets) find_package(Doxygen) if(DOXYGEN_FOUND) option(USE_DOT "Use dot program for generating graphical class diagrams with doxygen, if available" ON) mark_as_advanced(USE_DOT) set(HAVE_DOT "NO") if(DOXYGEN_DOT_EXECUTABLE AND USE_DOT) set(HAVE_DOT "YES") endif() -set(BLUEBERRY_DOCS_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH "BlueBerry output directory for all generated documentation.") -set(BLUEBERRY_DOXYGEN_OUTPUT_DIR ${BLUEBERRY_DOCS_OUTPUT_DIR}/reference/api CACHE INTERNAL "BlueBerry doxygen output directory") -set(BLUEBERRY_XPDOC_OUTPUT_DIR ${BLUEBERRY_DOCS_OUTPUT_DIR}/reference/extension-points) +if(NOT BLUEBERRY_DOCS_OUTPUT_DIR) + set(BLUEBERRY_DOCS_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH + "BlueBerry output directory for all generated documentation.") +endif() +if(NOT BLUEBERRY_DOXYGEN_OUTPUT_DIR) + set(BLUEBERRY_DOXYGEN_OUTPUT_DIR ${BLUEBERRY_DOCS_OUTPUT_DIR}/reference/api CACHE INTERNAL + "BlueBerry doxygen output directory") +endif() +if(NOT BLUEBERRY_XPDOC_OUTPUT_DIR) + set(BLUEBERRY_XPDOC_OUTPUT_DIR ${BLUEBERRY_DOCS_OUTPUT_DIR}/reference/extension-points) +endif() set(BLUEBERRY_DOXYGEN_TAGFILE_NAME ${BLUEBERRY_DOXYGEN_OUTPUT_DIR}/BlueBerry.tag CACHE INTERNAL "BlueBerry Doxygen tag file") # This is relative to the working directory of the doxygen command set(BLUEBERRY_DOXYGEN_STYLESHEET bb_doxygen.css) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${BLUEBERRY_DOXYGEN_STYLESHEET} ${CMAKE_CURRENT_BINARY_DIR}/${BLUEBERRY_DOXYGEN_STYLESHEET} @COPYONLY) file(RELATIVE_PATH BLUEBERRY_DOXYGEN_XP_RELATIVEDIR ${BLUEBERRY_DOXYGEN_OUTPUT_DIR}/html ${BLUEBERRY_XPDOC_OUTPUT_DIR}/) set(_doxygen_qt4bundles ) set(_doxygen_bundles ) set(_doxygen_binary_qt4bundles ) set(_doxygen_binary_bundles ) file(GLOB _bundle_dirs RELATIVE "${BLUEBERRY_PLUGINS_SOURCE_DIR}" "${BLUEBERRY_PLUGINS_SOURCE_DIR}/*") foreach(_bundle_dir ${_bundle_dirs}) string(REGEX MATCH "^\\..*" _matched_hidden "${_bundle_dir}") if(NOT _matched_hidden) if(IS_DIRECTORY "${BLUEBERRY_PLUGINS_SOURCE_DIR}/${_bundle_dir}") string(REGEX MATCH ".*\\.qt.*" _matched "${_bundle_dir}") if(_matched) if(QT4_FOUND) set(_doxygen_qt4bundles "${_doxygen_qt4bundles} \"${BLUEBERRY_PLUGINS_SOURCE_DIR}/${_bundle_dir}\"") set(_doxygen_binary_qt4bundles "${_doxygen_binary_qt4bundles} \"${BLUEBERRY_PLUGINS_BINARY_DIR}/${_bundle_dir}\"") endif() else() set(_doxygen_bundles "${_doxygen_bundles} \"${BLUEBERRY_PLUGINS_SOURCE_DIR}/${_bundle_dir}\"") set(_doxygen_binary_bundles "${_doxygen_binary_bundles} \"${BLUEBERRY_PLUGINS_BINARY_DIR}/${_bundle_dir}\"") endif() endif() endif() endforeach() # Compile a doxygen input filter for processing CMake scripts include(FunctionCMakeDoxygenFilterCompile) FunctionCMakeDoxygenFilterCompile(NAMESPACE "CMake") configure_file(doxygen.conf.in ${CMAKE_CURRENT_BINARY_DIR}/doxygen.conf) - -configure_file(reference/extension-points/index.dox.in - ${CMAKE_CURRENT_BINARY_DIR}/reference/extension-points/index.dox) find_package(Doxygen) -add_custom_target(BlueBerryDoc +add_custom_target(BlueBerryDoc ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.conf WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${_BlueBerryDoc_depends} ) - + # convert the extension points schema files into html if(ANT_FOUND AND BLUEBERRY_DOC_TOOLS_DIR) file(GLOB_RECURSE _plugin_xmls ${BLUEBERRY_PLUGINS_SOURCE_DIR}/plugin.xml) - MACRO_CONVERT_SCHEMA(INPUT ${_plugin_xmls} + MACRO_CONVERT_SCHEMA(INPUT ${_plugin_xmls} OUTPUT_DIR "${BLUEBERRY_XPDOC_OUTPUT_DIR}" TARGET_NAME BlueBerryXPDoc ) add_dependencies(BlueBerryDoc BlueBerryXPDoc) endif(ANT_FOUND AND BLUEBERRY_DOC_TOOLS_DIR) configure_file(schema.css ${BLUEBERRY_DOCS_OUTPUT_DIR}/schema.css) endif(DOXYGEN_FOUND) diff --git a/BlueBerry/Documentation/reference/extension-points/index.dox.in b/BlueBerry/Documentation/reference/extension-points/index.dox similarity index 97% rename from BlueBerry/Documentation/reference/extension-points/index.dox.in rename to BlueBerry/Documentation/reference/extension-points/index.dox index f9087bd2ee..8b6e7c33fa 100644 --- a/BlueBerry/Documentation/reference/extension-points/index.dox.in +++ b/BlueBerry/Documentation/reference/extension-points/index.dox @@ -1,64 +1,64 @@ /** -\page ExtPointsIndex Extension-Point Reference +\page BlueBerryExtPointsIndex Extension-Point Reference

BlueBerry Platform Extension Points

The following extension points can be used to extend the capabilities of the platform infrastructure:

Platform runtime

  • \subpage xp_org_blueberry_osgi_applications

Workbench

  • \subpage xp_org_blueberry_ui_editors
  • \subpage xp_org_blueberry_ui_perspectives
  • \subpage xp_org_blueberry_ui_presentationFactories
  • \subpage xp_org_blueberry_ui_services
  • \subpage xp_org_blueberry_ui_keywords
  • \subpage xp_org_blueberry_ui_preferencePages
  • \subpage xp_org_blueberry_ui_tweaklets
  • \subpage xp_org_blueberry_ui_views

Other

  • \subpage xp_org_blueberry_tests
\page xp_org_blueberry_osgi_applications org.blueberry.osgi.applications \htmlinclude org_blueberry_osgi_applications.html \page xp_org_blueberry_ui_editors org.blueberry.ui.editors \htmlinclude org_blueberry_ui_editors.html \page xp_org_blueberry_ui_perspectives org.blueberry.ui.perspectives \htmlinclude org_blueberry_ui_perspectives.html \page xp_org_blueberry_ui_presentationFactories org.blueberry.ui.presentationFactories \htmlinclude org_blueberry_ui_presentationFactories.html \page xp_org_blueberry_ui_services org.blueberry.ui.services \htmlinclude org_blueberry_ui_services.html \page xp_org_blueberry_ui_keywords org.blueberry.ui.keywords \htmlinclude org_blueberry_ui_keywords.html \page xp_org_blueberry_ui_preferencePages org.blueberry.ui.preferencePages \htmlinclude org_blueberry_ui_preferencePages.html \page xp_org_blueberry_ui_tweaklets org.blueberry.ui.tweaklets \htmlinclude org_blueberry_ui_tweaklets.html \page xp_org_blueberry_ui_views org.blueberry.ui.views \htmlinclude org_blueberry_ui_views.html \page xp_org_blueberry_tests org.blueberry.tests \htmlinclude org_blueberry_tests.html */ diff --git a/CMake/mitkMacroCreateModule.cmake b/CMake/mitkMacroCreateModule.cmake index 87f3707a6e..8a3a23afea 100644 --- a/CMake/mitkMacroCreateModule.cmake +++ b/CMake/mitkMacroCreateModule.cmake @@ -1,367 +1,374 @@ ################################################################## # # MITK_CREATE_MODULE # #! Creates a module for the automatic module dependency system within MITK. #! Configurations are generated in the moduleConf directory. #! #! USAGE: #! #! \code #! MITK_CREATE_MODULE( #! [INCLUDE_DIRS ] #! [INTERNAL_INCLUDE_DIRS ] #! [DEPENDS ] #! [PACKAGE_DEPENDS ] #! [TARGET_DEPENDS #! [EXPORT_DEFINE ] #! [QT_MODULE] #! [HEADERS_ONLY] #! [WARNINGS_AS_ERRORS] #! \endcode #! #! \param MODULE_NAME_IN The name for the new module #! \param HEADERS_ONLY specify this if the modules just contains header files. ################################################################## macro(MITK_CREATE_MODULE MODULE_NAME_IN) set(_macro_params SUBPROJECTS # list of CDash labels VERSION # module version number, e.g. "1.2.0" INCLUDE_DIRS # exported include dirs (used in mitkMacroCreateModuleConf.cmake) INTERNAL_INCLUDE_DIRS # include dirs internal to this module DEPENDS # list of modules this module depends on DEPENDS_INTERNAL # list of modules this module internally depends on PACKAGE_DEPENDS # list of "packages this module depends on (e.g. Qt, VTK, etc.) TARGET_DEPENDS # list of CMake targets this module should depend on EXPORT_DEFINE # export macro name for public symbols of this module AUTOLOAD_WITH # a module target name identifying the module which will trigger the # automatic loading of this module ADDITIONAL_LIBS # list of addidtional libraries linked to this module GENERATED_CPP # not used (?) ) set(_macro_options QT_MODULE # the module makes use of Qt features and needs moc and ui generated files FORCE_STATIC # force building this module as a static library HEADERS_ONLY # this module is a headers-only library GCC_DEFAULT_VISIBILITY # do not use gcc visibility flags - all symbols will be exported NO_INIT # do not create CppMicroServices initialization code WARNINGS_AS_ERRORS # treat all compiler warnings as errors ) MACRO_PARSE_ARGUMENTS(MODULE "${_macro_params}" "${_macro_options}" ${ARGN}) set(MODULE_NAME ${MODULE_NAME_IN}) if(MODULE_HEADERS_ONLY) set(MODULE_PROVIDES ) if(MODULE_AUTOLOAD_WITH) message(SEND_ERROR "A headers only module cannot be auto-loaded") endif() else() set(MODULE_PROVIDES ${MODULE_NAME}) if(NOT MODULE_NO_INIT AND NOT MODULE_NAME STREQUAL "Mitk") # Add a dependency to the "Mitk" module list(APPEND MODULE_DEPENDS Mitk) endif() endif() if(NOT MODULE_SUBPROJECTS) if(MITK_DEFAULT_SUBPROJECTS) set(MODULE_SUBPROJECTS ${MITK_DEFAULT_SUBPROJECTS}) endif() endif() # check if the subprojects exist as targets if(MODULE_SUBPROJECTS) foreach(subproject ${MODULE_SUBPROJECTS}) if(NOT TARGET ${subproject}) message(SEND_ERROR "The subproject ${subproject} does not have a corresponding target") endif() endforeach() endif() # check and set-up auto-loading if(MODULE_AUTOLOAD_WITH) if(NOT TARGET "${MODULE_AUTOLOAD_WITH}") message(SEND_ERROR "The module target \"${MODULE_AUTOLOAD_WITH}\" specified as the auto-loading module for \"${MODULE_NAME}\" does not exist") endif() # create a meta-target if it does not already exist set(_module_autoload_meta_target "${MODULE_AUTOLOAD_WITH}-universe") if(NOT TARGET ${_module_autoload_meta_target}) add_custom_target(${_module_autoload_meta_target}) endif() endif() # assume worst case set(MODULE_IS_ENABLED 0) # first we check if we have an explicit module build list if(MITK_MODULES_TO_BUILD) list(FIND MITK_MODULES_TO_BUILD ${MODULE_NAME} _MOD_INDEX) if(_MOD_INDEX EQUAL -1) set(MODULE_IS_EXCLUDED 1) endif() endif() if(NOT MODULE_IS_EXCLUDED AND NOT (MODULE_QT_MODULE AND NOT MITK_USE_QT)) # first of all we check for the dependencies MITK_CHECK_MODULE(_MISSING_DEP ${MODULE_DEPENDS}) if(_MISSING_DEP) message("Module ${MODULE_NAME} won't be built, missing dependency: ${_MISSING_DEP}") set(MODULE_IS_ENABLED 0) else(_MISSING_DEP) set(MODULE_IS_ENABLED 1) # now check for every package if it is enabled. This overlaps a bit with # MITK_CHECK_MODULE ... foreach(_package ${MODULE_PACKAGE_DEPENDS}) if((DEFINED MITK_USE_${_package}) AND NOT (MITK_USE_${_package})) message("Module ${MODULE_NAME} won't be built. Turn on MITK_USE_${_package} if you want to use it.") set(MODULE_IS_ENABLED 0) endif() endforeach() if(MODULE_IS_ENABLED) # clear variables defined in files.cmake set(RESOURCE_FILES ) set(CPP_FILES ) set(H_FILES ) set(TXX_FILES ) set(DOX_FILES ) set(UI_FILES ) set(MOC_H_FILES ) set(QRC_FILES ) # clear other variables set(Q${KITNAME}_GENERATED_MOC_CPP ) set(Q${KITNAME}_GENERATED_QRC_CPP ) set(Q${KITNAME}_GENERATED_UI_CPP ) _MITK_CREATE_MODULE_CONF() if(NOT MODULE_EXPORT_DEFINE) set(MODULE_EXPORT_DEFINE ${MODULE_NAME}_EXPORT) endif(NOT MODULE_EXPORT_DEFINE) if(MITK_GENERATE_MODULE_DOT) message("MODULEDOTNAME ${MODULE_NAME}") foreach(dep ${MODULE_DEPENDS}) message("MODULEDOT \"${MODULE_NAME}\" -> \"${dep}\" ; ") endforeach(dep) endif(MITK_GENERATE_MODULE_DOT) set(DEPENDS "${MODULE_DEPENDS}") set(DEPENDS_BEFORE "not initialized") set(PACKAGE_DEPENDS "${MODULE_PACKAGE_DEPENDS}") MITK_USE_MODULE("${MODULE_DEPENDS}") # ok, now create the module itself include_directories(. ${ALL_INCLUDE_DIRECTORIES}) include(files.cmake) set(module_compile_flags ) if(WIN32) set(module_compile_flags "${module_compile_flags} -DPOCO_NO_UNWINDOWS -DWIN32_LEAN_AND_MEAN") endif() if(MODULE_GCC_DEFAULT_VISIBILITY) set(use_visibility_flags 0) else() # We only support hidden visibility for gcc for now. Clang 3.0 still has troubles with # correctly marking template declarations and explicit template instantiations as exported. # See http://comments.gmane.org/gmane.comp.compilers.clang.scm/50028 # and http://llvm.org/bugs/show_bug.cgi?id=10113 if(CMAKE_COMPILER_IS_GNUCXX) set(use_visibility_flags 1) else() # set(use_visibility_flags 0) endif() endif() if(CMAKE_COMPILER_IS_GNUCXX) # MinGW does not export all symbols automatically, so no need to set flags. # # With gcc < 4.5, RTTI symbols from classes declared in third-party libraries # which are not "gcc visibility aware" are marked with hidden visibility in # DSOs which include the class declaration and which are compiled with # hidden visibility. This leads to dynamic_cast and exception handling problems. # While this problem could be worked around by sandwiching the include # directives for the third-party headers between "#pragma visibility push/pop" # statements, it is generally safer to just use default visibility with # gcc < 4.5. if(${GCC_VERSION} VERSION_LESS "4.5" OR MINGW) set(use_visibility_flags 0) endif() endif() if(use_visibility_flags) mitkFunctionCheckCompilerFlags("-fvisibility=hidden" module_compile_flags) mitkFunctionCheckCompilerFlags("-fvisibility-inlines-hidden" module_compile_flags) endif() configure_file(${MITK_SOURCE_DIR}/CMake/moduleExports.h.in ${CMAKE_BINARY_DIR}/${MODULES_CONF_DIRNAME}/${MODULE_NAME}Exports.h @ONLY) if(MODULE_WARNINGS_AS_ERRORS) if(MSVC_VERSION) mitkFunctionCheckCompilerFlags("/WX" module_compile_flags) else() mitkFunctionCheckCompilerFlags("-Werror" module_compile_flags) # The flag "c++0x-static-nonintegral-init" has been renamed in newer Clang # versions to "static-member-init", see # http://clang-developers.42468.n3.nabble.com/Wc-0x-static-nonintegral-init-gone-td3999651.html # # Also, older Clang and seemingly all gcc versions do not warn if unknown # "-no-*" flags are used, so CMake will happily append any -Wno-* flag to the # command line. This may get confusing if unrelated compiler errors happen and # the error output then additinally contains errors about unknown flags (which # is not the case if there were no compile errors). # # So instead of using -Wno-* we use -Wno-error=*, which will be properly rejected by # the compiler and if applicable, prints the specific warning as a real warning and # not as an error (although -Werror was given). mitkFunctionCheckCompilerFlags("-Wno-error=c++0x-static-nonintegral-init" module_compile_flags) mitkFunctionCheckCompilerFlags("-Wno-error=gnu" module_compile_flags) + + # VNL headers throw a lot of these, not fixable for us at least in ITK 3 + mitkFunctionCheckCompilerFlags("-Wno-error=unused-parameter" module_compile_flags) + + # Some DICOM header file in ITK + mitkFunctionCheckCompilerFlags("-Wno-error=cast-align" module_compile_flags) + endif() endif(MODULE_WARNINGS_AS_ERRORS) if(MODULE_FORCE_STATIC) set(_STATIC STATIC) else() set(_STATIC ) endif(MODULE_FORCE_STATIC) if(NOT MODULE_NO_INIT) set(MODULE_LIBNAME ${MODULE_PROVIDES}) usFunctionGenerateModuleInit(CPP_FILES NAME ${MODULE_NAME} LIBRARY_NAME ${MODULE_LIBNAME} DEPENDS ${MODULE_DEPENDS} ${MODULE_DEPENDS_INTERNAL} ${MODULE_PACKAGE_DEPENDS} #VERSION ${MODULE_VERSION} ) if(RESOURCE_FILES) usFunctionEmbedResources(CPP_FILES LIBRARY_NAME ${MODULE_LIBNAME} ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Resources FILES ${RESOURCE_FILES}) endif() endif() if(MODULE_QT_MODULE) if(UI_FILES) QT4_WRAP_UI(Q${KITNAME}_GENERATED_UI_CPP ${UI_FILES}) endif(UI_FILES) if(MOC_H_FILES) QT4_WRAP_CPP(Q${KITNAME}_GENERATED_MOC_CPP ${MOC_H_FILES}) endif(MOC_H_FILES) if(QRC_FILES) QT4_ADD_RESOURCES(Q${KITNAME}_GENERATED_QRC_CPP ${QRC_FILES}) endif(QRC_FILES) set(Q${KITNAME}_GENERATED_CPP ${Q${KITNAME}_GENERATED_CPP} ${Q${KITNAME}_GENERATED_UI_CPP} ${Q${KITNAME}_GENERATED_MOC_CPP} ${Q${KITNAME}_GENERATED_QRC_CPP}) endif() ORGANIZE_SOURCES(SOURCE ${CPP_FILES} HEADER ${H_FILES} TXX ${TXX_FILES} DOC ${DOX_FILES} UI ${UI_FILES} QRC ${QRC_FILES} MOC ${Q${KITNAME}_GENERATED_MOC_CPP} GEN_QRC ${Q${KITNAME}_GENERATED_QRC_CPP} GEN_UI ${Q${KITNAME}_GENERATED_UI_CPP}) set(coverage_sources ${CPP_FILES} ${H_FILES} ${GLOBBED__H_FILES} ${CORRESPONDING__H_FILES} ${TXX_FILES} ${TOOL_CPPS} ${TOOL_GUI_CPPS}) if(MODULE_SUBPROJECTS) set_property(SOURCE ${coverage_sources} APPEND PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) endif() if(NOT MODULE_HEADERS_ONLY) if(ALL_LIBRARY_DIRS) # LINK_DIRECTORIES applies only to targets which are added after the call to LINK_DIRECTORIES link_directories(${ALL_LIBRARY_DIRS}) endif(ALL_LIBRARY_DIRS) add_library(${MODULE_PROVIDES} ${_STATIC} ${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP} ${DOX_FILES} ${UI_FILES} ${QRC_FILES}) if(MODULE_TARGET_DEPENDS) add_dependencies(${MODULE_PROVIDES} ${MODULE_TARGET_DEPENDS}) endif() if(MODULE_SUBPROJECTS) set_property(TARGET ${MODULE_PROVIDES} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) foreach(subproject ${MODULE_SUBPROJECTS}) add_dependencies(${subproject} ${MODULE_PROVIDES}) endforeach() endif() if(ALL_LIBRARIES) target_link_libraries(${MODULE_PROVIDES} ${ALL_LIBRARIES}) endif(ALL_LIBRARIES) if(MODULE_QT_MODULE AND QT_LIBRARIES) target_link_libraries(${MODULE_PROVIDES} ${QT_LIBRARIES}) endif() if(MINGW) target_link_libraries(${MODULE_PROVIDES} ssp) # add stack smash protection lib endif() # Apply properties to the module target. set_target_properties(${MODULE_PROVIDES} PROPERTIES COMPILE_FLAGS "${module_compile_flags}") # add the target name to a global property which is used in the top-level # CMakeLists.txt file to export the target set_property(GLOBAL APPEND PROPERTY MITK_MODULE_TARGETS ${MODULE_PROVIDES}) if(MODULE_AUTOLOAD_WITH) # for auto-loaded modules, adapt the output directory add_dependencies(${_module_autoload_meta_target} ${MODULE_PROVIDES}) if(WIN32) set(_module_output_prop RUNTIME_OUTPUT_DIRECTORY) else() set(_module_output_prop LIBRARY_OUTPUT_DIRECTORY) endif() set(_module_output_dir ${CMAKE_${_module_output_prop}}/${MODULE_AUTOLOAD_WITH}) get_target_property(_module_is_imported ${MODULE_AUTOLOAD_WITH} IMPORTED) if(NOT _module_is_imported) # if the auto-loading module is not imported, get its location # and put the auto-load module relative to it. get_target_property(_module_output_dir ${MODULE_AUTOLOAD_WITH} ${_module_output_prop}) set_target_properties(${MODULE_PROVIDES} PROPERTIES ${_module_output_prop} ${_module_output_dir}/${MODULE_AUTOLOAD_WITH}) else() set_target_properties(${MODULE_PROVIDES} PROPERTIES ${_module_output_prop} ${CMAKE_${_module_output_prop}}/${MODULE_AUTOLOAD_WITH}) endif() set_target_properties(${MODULE_PROVIDES} PROPERTIES MITK_AUTOLOAD_DIRECTORY ${MODULE_AUTOLOAD_WITH}) # add the auto-load module name as a property set_property(TARGET ${MODULE_AUTOLOAD_WITH} APPEND PROPERTY MITK_AUTOLOAD_TARGETS ${MODULE_PROVIDES}) else() # Add meta dependencies (e.g. on auto-load modules from depending modules) if(ALL_META_DEPENDENCIES) add_dependencies(${MODULE_PROVIDES} ${ALL_META_DEPENDENCIES}) endif() endif() endif() endif(MODULE_IS_ENABLED) endif(_MISSING_DEP) endif(NOT MODULE_IS_EXCLUDED AND NOT (MODULE_QT_MODULE AND NOT MITK_USE_QT)) if(NOT MODULE_IS_ENABLED) _MITK_CREATE_MODULE_CONF() endif(NOT MODULE_IS_ENABLED) endmacro(MITK_CREATE_MODULE) diff --git a/CMake/mitkMacroCreateModuleTests.cmake b/CMake/mitkMacroCreateModuleTests.cmake index c10927ae34..7820e68174 100644 --- a/CMake/mitkMacroCreateModuleTests.cmake +++ b/CMake/mitkMacroCreateModuleTests.cmake @@ -1,85 +1,90 @@ # # Create tests and testdriver for this module # # Usage: MITK_CREATE_MODULE_TESTS( [EXTRA_DRIVER_INIT init_code] ) # # EXTRA_DRIVER_INIT is inserted as c++ code in the testdriver and will be executed before each test # macro(MITK_CREATE_MODULE_TESTS) MACRO_PARSE_ARGUMENTS(MODULE_TEST - "EXTRA_DRIVER_INIT;EXTRA_DRIVER_INCLUDE" "" ${ARGN}) + "EXTRA_DRIVER_INIT;EXTRA_DRIVER_INCLUDE;EXTRA_DEPENDS" "" ${ARGN}) if(BUILD_TESTING AND MODULE_IS_ENABLED) set(OLD_MOC_H_FILES ${MOC_H_FILES}) set(MOC_H_FILES) include(files.cmake) include_directories(.) if(DEFINED MOC_H_FILES) QT4_WRAP_CPP(MODULE_TEST_GENERATED_MOC_CPP ${MOC_H_FILES}) endif(DEFINED MOC_H_FILES) + if (MODULE_TEST_EXTRA_DEPENDS) + MITK_USE_MODULE("${MODULE_TEST_EXTRA_DEPENDS}") + include_directories(${ALL_INCLUDE_DIRECTORIES}) + endif() + set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN "mitk::LoggingBackend::Register(); ${MODULE_TEST_EXTRA_DRIVER_INIT};") set(CMAKE_TESTDRIVER_AFTER_TESTMAIN "mitk::LoggingBackend::Unregister();") if(NOT MODULE_TEST_EXTRA_DRIVER_INCLUDE) # this is necessary to make the LoggingBackend calls available if nothing else is included set(MODULE_TEST_EXTRA_DRIVER_INCLUDE "mitkLog.h") endif(NOT MODULE_TEST_EXTRA_DRIVER_INCLUDE) create_test_sourcelist(MODULETEST_SOURCE ${MODULE_NAME}TestDriver.cpp ${MODULE_TESTS} ${MODULE_IMAGE_TESTS} ${MODULE_CUSTOM_TESTS} EXTRA_INCLUDE ${MODULE_TEST_EXTRA_DRIVER_INCLUDE} ) set(TESTDRIVER ${MODULE_NAME}TestDriver) add_executable(${TESTDRIVER} ${MODULETEST_SOURCE} ${MODULE_TEST_GENERATED_MOC_CPP} ${TEST_CPP_FILES}) target_link_libraries(${TESTDRIVER} ${MODULE_PROVIDES} ${ALL_LIBRARIES}) if(MODULE_SUBPROJECTS) foreach(subproject ${MODULE_SUBPROJECTS}) add_dependencies(${subproject} ${TESTDRIVER}) endforeach() endif() # # Now tell CMake which tests should be run. This is done automatically # for all tests in ${KITNAME}_TESTS and ${KITNAME}_IMAGE_TESTS. The IMAGE_TESTS # are run for each image in the TESTIMAGES list. # foreach( test ${MODULE_TESTS} ) get_filename_component(TName ${test} NAME_WE) add_test(${TName} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} ${TName}) # Add labels for CDash subproject support if(MODULE_SUBPROJECTS) set_property(TEST ${TName} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) endif() endforeach( test ) foreach(image ${MODULE_TESTIMAGES} ${ADDITIONAL_TEST_IMAGES} ) if(EXISTS ${image}) set(IMAGE_FULL_PATH ${image}) else(EXISTS ${image}) # todo: maybe search other paths as well # yes, please in mitk/Testing/Data, too set(IMAGE_FULL_PATH ${MITK_DATA_DIR}/${image}) endif(EXISTS ${image}) if(EXISTS ${IMAGE_FULL_PATH}) foreach( test ${MODULE_IMAGE_TESTS} ) get_filename_component(TName ${test} NAME_WE) get_filename_component(ImageName ${IMAGE_FULL_PATH} NAME) add_test(${TName}_${ImageName} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${TESTDRIVER} ${TName} ${IMAGE_FULL_PATH}) # Add labels for CDash subproject support if(MODULE_SUBPROJECTS) set_property(TEST ${TName}_${ImageName} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) endif() endforeach( test ) else(EXISTS ${IMAGE_FULL_PATH}) message("!!!!! No such file: ${IMAGE_FULL_PATH} !!!!!") endif(EXISTS ${IMAGE_FULL_PATH}) endforeach( image ) set(MOC_H_FILES ${OLD_MOC_H_FILES}) endif(BUILD_TESTING AND MODULE_IS_ENABLED) endmacro(MITK_CREATE_MODULE_TESTS) diff --git a/CMake/mitkSetupVariables.cmake b/CMake/mitkSetupVariables.cmake index 515ee84fde..d233b8b0b2 100644 --- a/CMake/mitkSetupVariables.cmake +++ b/CMake/mitkSetupVariables.cmake @@ -1,165 +1,169 @@ if(MITK_BUILD_ALL_PLUGINS) set(MITK_BUILD_ALL_PLUGINS_OPTION "FORCE_BUILD_ALL") endif() set(LIBPOSTFIX "") # MITK_VERSION set(MITK_VERSION_MAJOR "2012") set(MITK_VERSION_MINOR "12") set(MITK_VERSION_PATCH "99") set(MITK_VERSION_STRING "${MITK_VERSION_MAJOR}.${MITK_VERSION_MINOR}.${MITK_VERSION_PATCH}") if(MITK_VERSION_PATCH STREQUAL "99") set(MITK_VERSION_STRING "${MITK_VERSION_STRING}-${MITK_REVISION_SHORTID}") endif() +# Needed early on for redirecting the BlueBerry documentation output dir +set(MITK_DOXYGEN_OUTPUT_DIR ${PROJECT_BINARY_DIR}/Documentation/Doxygen CACHE PATH + "Output directory for doxygen generated documentation." ) + #----------------------------------- # Configuration of module system #----------------------------------- set(MODULES_CONF_DIRNAME modulesConf) set(MODULES_CONF_DIRS ${MITK_BINARY_DIR}/${MODULES_CONF_DIRNAME}) if(NOT UNIX AND NOT MINGW) set(MITK_WIN32_FORCE_STATIC "STATIC" CACHE INTERNAL "Use this variable to always build static libraries on non-unix platforms") endif() # build the MITK_INCLUDE_DIRS variable set(MITK_INCLUDE_DIRS ${ITK_INCLUDE_DIRS} ${VTK_INCLUDE_DIRS} ${PROJECT_BINARY_DIR} # contains mitkConfig.h and similar files ${MODULES_CONF_DIRS} # contains module *Exports.h files ) set(CORE_DIRECTORIES Common DataManagement Algorithms IO Rendering Interactions Controllers Service) foreach(d ${CORE_DIRECTORIES}) list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/Core/Code/${d}) endforeach() #list(APPEND MITK_INCLUDE_DIRS #${ITK_INCLUDE_DIRS} #${VTK_INCLUDE_DIRS} # ) foreach(d Utilities Utilities/ipPic Utilities/pic2vtk Utilities/tinyxml Utilities/mbilog) list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/${d}) endforeach() list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/Utilities/mbilog) if(WIN32) list(APPEND MITK_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipPic/win32) endif() # additional include dirs variables set(ANN_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ann/include) set(IPSEGMENTATION_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipSegmentation) # variables containing librariy names set(MITK_CORE_LIBRARIES Mitk) set(VTK_FOR_MITK_LIBRARIES vtkGraphics vtkCommon vtkFiltering vtkGraphics vtkHybrid vtkImaging vtkIO vtkParallel vtkRendering vtkVolumeRendering vtkWidgets ${VTK_JPEG_LIBRARIES} ${VTK_PNG_LIBRARIES} ${VTK_ZLIB_LIBRARIES} ${VTK_EXPAT_LIBRARIES} ${VTK_FREETYPE_LIBRARIES} ) # TODO: maybe solve this with lib depends mechanism of CMake set(UTIL_FOR_MITK_LIBRARIES mitkIpPic mitkIpFunc mbilog) set(LIBRARIES_FOR_MITK_CORE ${UTIL_FOR_MITK_LIBRARIES} ${VTK_FOR_MITK_LIBRARIES} ${ITK_LIBRARIES} ) set(MITK_LIBRARIES ${MITK_CORE_LIBRARIES} ${LIBRARIES_FOR_MITK_CORE} pic2vtk ipSegmentation ann ) # variables used in CMake macros which are called from external projects set(MITK_VTK_LIBRARY_DIRS ${VTK_LIBRARY_DIRS}) set(MITK_ITK_LIBRARY_DIRS ${ITK_LIBRARY_DIRS}) # variables containing link directories set(MITK_LIBRARY_DIRS ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) set(MITK_LINK_DIRECTORIES ${CMAKE_LIBRARY_OUTPUT_DIRECTORY} ${ITK_LIBRARY_DIRS} ${VTK_LIBRARY_DIRS} ${GDCM_LIBRARY_DIRS}) # Qt support if(MITK_USE_QT) find_package(Qt4 REQUIRED) set(QMITK_INCLUDE_DIRS ${MITK_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/Modules/Qmitk ${PROJECT_BINARY_DIR}/Modules/Qmitk ) set(QMITK_LIBRARIES Qmitk ${MITK_LIBRARIES}) set(QMITK_LINK_DIRECTORIES ${MITK_LINK_DIRECTORIES}) endif() if(MITK_BUILD_ALL_PLUGINS) set(MITK_BUILD_ALL_PLUGINS_OPTION "FORCE_BUILD_ALL") endif() # create a list of types for template instantiations of itk image access functions function(_create_type_seq TYPES seq_var seqdim_var) set(_seq ) set(_seq_dim ) string(REPLACE "," ";" _pixeltypes "${TYPES}") foreach(_pixeltype ${_pixeltypes}) set(_seq "${_seq}(${_pixeltype})") set(_seq_dim "${_seq_dim}((${_pixeltype},dim))") endforeach() set(${seq_var} "${_seq}" PARENT_SCOPE) set(${seqdim_var} "${_seq_dim}" PARENT_SCOPE) endfunction() set(MITK_ACCESSBYITK_PIXEL_TYPES ) set(MITK_ACCESSBYITK_PIXEL_TYPES_SEQ ) set(MITK_ACCESSBYITK_TYPES_DIMN_SEQ ) # concatenate only the simple pixel types to the MITK_ACCESSBYITK_PIXEL_TYPE_SEQ list # see Bug 12682 for detailed information foreach(_type INTEGRAL FLOATING) set(_typelist "${MITK_ACCESSBYITK_${_type}_PIXEL_TYPES}") if(_typelist) if(MITK_ACCESSBYITK_PIXEL_TYPES) set(MITK_ACCESSBYITK_PIXEL_TYPES "${MITK_ACCESSBYITK_PIXEL_TYPES},${_typelist}") else() set(MITK_ACCESSBYITK_PIXEL_TYPES "${_typelist}") endif() endif() _create_type_seq("${_typelist}" MITK_ACCESSBYITK_${_type}_PIXEL_TYPES_SEQ MITK_ACCESSBYITK_${_type}_TYPES_DIMN_SEQ) set(MITK_ACCESSBYITK_PIXEL_TYPES_SEQ "${MITK_ACCESSBYITK_PIXEL_TYPES_SEQ}${MITK_ACCESSBYITK_${_type}_PIXEL_TYPES_SEQ}") set(MITK_ACCESSBYITK_TYPES_DIMN_SEQ "${MITK_ACCESSBYITK_TYPES_DIMN_SEQ}${MITK_ACCESSBYITK_${_type}_TYPES_DIMN_SEQ}") endforeach() # separate processing of the COMPOSITE list to avoid its concatenation to to global list _create_type_seq(${MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES} MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES_SEQ MITK_ACCESSBYITK_COMPOSITE_TYPES_DIMN_SEQ) set(MITK_ACCESSBYITK_DIMENSIONS_SEQ ) string(REPLACE "," ";" _dimensions "${MITK_ACCESSBYITK_DIMENSIONS}") foreach(_dimension ${_dimensions}) set(MITK_ACCESSBYITK_DIMENSIONS_SEQ "${MITK_ACCESSBYITK_DIMENSIONS_SEQ}(${_dimension})") endforeach() diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f135c68c0..333f3c1b1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,949 +1,963 @@ if(APPLE) # With XCode 4.3, the SDK location changed. Older CMake # versions are not able to find it. cmake_minimum_required(VERSION 2.8.8) else() cmake_minimum_required(VERSION 2.8.4) endif() #----------------------------------------------------------------------------- # Set a default build type if none was specified #----------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Debug' as none was specified.") set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() #----------------------------------------------------------------------------- # Superbuild Option - Enabled by default #----------------------------------------------------------------------------- option(MITK_USE_SUPERBUILD "Build MITK and the projects it depends on via SuperBuild.cmake." ON) if(MITK_USE_SUPERBUILD) project(MITK-superbuild) set(MITK_SOURCE_DIR ${PROJECT_SOURCE_DIR}) set(MITK_BINARY_DIR ${PROJECT_BINARY_DIR}) else() project(MITK) endif() #----------------------------------------------------------------------------- # Warn if source or build path is too long #----------------------------------------------------------------------------- if(WIN32) set(_src_dir_length_max 50) set(_bin_dir_length_max 50) if(MITK_USE_SUPERBUILD) set(_src_dir_length_max 43) # _src_dir_length_max - strlen(ITK-src) set(_bin_dir_length_max 40) # _bin_dir_length_max - strlen(MITK-build) endif() string(LENGTH "${MITK_SOURCE_DIR}" _src_n) string(LENGTH "${MITK_BINARY_DIR}" _bin_n) # The warnings should be converted to errors if(_src_n GREATER _src_dir_length_max) message(WARNING "MITK source code directory path length is too long (${_src_n} > ${_src_dir_length_max})." "Please move the MITK source code directory to a directory with a shorter path." ) endif() if(_bin_n GREATER _bin_dir_length_max) message(WARNING "MITK build directory path length is too long (${_bin_n} > ${_bin_dir_length_max})." "Please move the MITK build directory to a directory with a shorter path." ) endif() endif() #----------------------------------------------------------------------------- # See http://cmake.org/cmake/help/cmake-2-8-docs.html#section_Policies for details #----------------------------------------------------------------------------- set(project_policies CMP0001 # NEW: CMAKE_BACKWARDS_COMPATIBILITY should no longer be used. CMP0002 # NEW: Logical target names must be globally unique. CMP0003 # NEW: Libraries linked via full path no longer produce linker search paths. CMP0004 # NEW: Libraries linked may NOT have leading or trailing whitespace. CMP0005 # NEW: Preprocessor definition values are now escaped automatically. CMP0006 # NEW: Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION. CMP0007 # NEW: List command no longer ignores empty elements. CMP0008 # NEW: Libraries linked by full-path must have a valid library file name. CMP0009 # NEW: FILE GLOB_RECURSE calls should not follow symlinks by default. CMP0010 # NEW: Bad variable reference syntax is an error. CMP0011 # NEW: Included scripts do automatic cmake_policy PUSH and POP. CMP0012 # NEW: if() recognizes numbers and boolean constants. CMP0013 # NEW: Duplicate binary directories are not allowed. CMP0014 # NEW: Input directories must have CMakeLists.txt ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # Update CMake module path #------------------------------------------------------------------------------ set(CMAKE_MODULE_PATH ${MITK_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(mitkMacroEmptyExternalProject) include(mitkFunctionGenerateProjectXml) include(mitkFunctionSuppressWarnings) SUPPRESS_VC_DEPRECATED_WARNINGS() #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- foreach(type LIBRARY RUNTIME ARCHIVE) # Make sure the directory exists if(DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY AND NOT EXISTS ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) message("Creating directory MITK_CMAKE_${type}_OUTPUT_DIRECTORY: ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") file(MAKE_DIRECTORY "${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") endif() if(MITK_USE_SUPERBUILD) set(output_dir ${MITK_BINARY_DIR}/bin) if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(MITK_CMAKE_${type}_OUTPUT_DIRECTORY ${MITK_BINARY_DIR}/MITK-build/bin) endif() else() if(NOT DEFINED MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(output_dir ${MITK_BINARY_DIR}/bin) else() set(output_dir ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) endif() endif() set(CMAKE_${type}_OUTPUT_DIRECTORY ${output_dir} CACHE INTERNAL "Single output directory for building all libraries.") mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY) endforeach() #----------------------------------------------------------------------------- # Additional MITK Options (also shown during superbuild) #----------------------------------------------------------------------------- option(BUILD_SHARED_LIBS "Build MITK with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) option(MITK_BUILD_ALL_APPS "Build all MITK applications" OFF) set(MITK_BUILD_TUTORIAL OFF CACHE INTERNAL "Deprecated! Use MITK_BUILD_EXAMPLES instead!") option(MITK_BUILD_EXAMPLES "Build the MITK Examples" ${MITK_BUILD_TUTORIAL}) option(MITK_USE_Boost "Use the Boost C++ library" OFF) option(MITK_USE_BLUEBERRY "Build the BlueBerry platform" ON) option(MITK_USE_CTK "Use CTK in MITK" ${MITK_USE_BLUEBERRY}) option(MITK_USE_QT "Use Nokia's Qt library" ${MITK_USE_CTK}) option(MITK_USE_DCMTK "EXPERIMENTAL, superbuild only: Use DCMTK in MITK" ${MITK_USE_CTK}) option(MITK_DCMTK_BUILD_SHARED_LIBS "EXPERIMENTAL, superbuild only: build DCMTK as shared libs" OFF) option(MITK_USE_OpenCV "Use Intel's OpenCV library" OFF) option(MITK_USE_OpenCL "Use OpenCL GPU-Computing library" OFF) option(MITK_USE_SOFA "Use Simulation Open Framework Architecture" OFF) option(MITK_USE_Python "Use Python wrapping in MITK" OFF) set(MITK_USE_CableSwig ${MITK_USE_Python}) mark_as_advanced(MITK_BUILD_ALL_APPS MITK_USE_CTK MITK_USE_DCMTK ) if(MITK_USE_Boost) option(MITK_USE_SYSTEM_Boost "Use the system Boost" OFF) set(MITK_USE_Boost_LIBRARIES "" CACHE STRING "A semi-colon separated list of required Boost libraries") endif() if(MITK_USE_BLUEBERRY) option(MITK_BUILD_ALL_PLUGINS "Build all MITK plugins" OFF) mark_as_advanced(MITK_BUILD_ALL_PLUGINS) if(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() endif() if(MITK_USE_CTK) if(NOT MITK_USE_QT) message("Forcing MITK_USE_QT to ON because of MITK_USE_CTK") set(MITK_USE_QT ON CACHE BOOL "Use Nokia's Qt library in MITK" FORCE) endif() if(NOT MITK_USE_DCMTK) message("Setting MITK_USE_DCMTK to ON because DCMTK needs to be build for CTK") set(MITK_USE_DCMTK ON CACHE BOOL "Use DCMTK in MITK" FORCE) endif() endif() if(MITK_USE_QT) # find the package at the very beginning, so that QT4_FOUND is available find_package(Qt4 4.6.2 REQUIRED) endif() # Customize the default pixel types for multiplex macros 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 "itk::RGBPixel, itk::RGBAPixel" 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") mark_as_advanced(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES MITK_ACCESSBYITK_DIMENSIONS ) # consistency checks if(NOT MITK_ACCESSBYITK_INTEGRAL_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" FORCE) endif() if(NOT MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES) set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES) set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_DIMENSIONS) set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") endif() #----------------------------------------------------------------------------- # Additional CXX/C Flags #----------------------------------------------------------------------------- set(ADDITIONAL_C_FLAGS "" CACHE STRING "Additional C Flags") mark_as_advanced(ADDITIONAL_C_FLAGS) set(ADDITIONAL_CXX_FLAGS "" CACHE STRING "Additional CXX Flags") mark_as_advanced(ADDITIONAL_CXX_FLAGS) #----------------------------------------------------------------------------- # Project.xml #----------------------------------------------------------------------------- # A list of topologically ordered targets set(CTEST_PROJECT_SUBPROJECTS) if(MITK_USE_BLUEBERRY) list(APPEND CTEST_PROJECT_SUBPROJECTS BlueBerry) endif() list(APPEND CTEST_PROJECT_SUBPROJECTS MITK-Core MITK-CoreUI MITK-IGT MITK-ToF MITK-DTI MITK-Registration MITK-Modules # all modules not contained in a specific subproject MITK-Plugins # all plugins not contained in a specific subproject MITK-Examples Unlabeled # special "subproject" catching all unlabeled targets and tests ) # Configure CTestConfigSubProject.cmake that could be used by CTest scripts configure_file(${MITK_SOURCE_DIR}/CTestConfigSubProject.cmake.in ${MITK_BINARY_DIR}/CTestConfigSubProject.cmake) if(CTEST_PROJECT_ADDITIONAL_TARGETS) # those targets will be executed at the end of the ctest driver script # and they also get their own subproject label set(subproject_list "${CTEST_PROJECT_SUBPROJECTS};${CTEST_PROJECT_ADDITIONAL_TARGETS}") else() set(subproject_list "${CTEST_PROJECT_SUBPROJECTS}") endif() # Generate Project.xml file expected by the CTest driver script mitkFunctionGenerateProjectXml(${MITK_BINARY_DIR} MITK "${subproject_list}" ${MITK_USE_SUPERBUILD}) #----------------------------------------------------------------------------- # Superbuild script #----------------------------------------------------------------------------- if(MITK_USE_SUPERBUILD) include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake") return() endif() #***************************************************************************** #**************************** END OF SUPERBUILD **************************** #***************************************************************************** #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(CheckCXXSourceCompiles) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionGetGccVersion) include(MacroParseArguments) include(mitkFunctionSuppressWarnings) # includes several functions include(mitkFunctionOrganizeSources) include(mitkFunctionGetVersion) include(mitkFunctionGetVersionDescription) include(mitkFunctionCreateWindowsBatchScript) include(mitkFunctionInstallProvisioningFiles) include(mitkFunctionInstallAutoLoadModules) include(mitkFunctionCompileSnippets) include(mitkMacroCreateModuleConf) include(mitkMacroCreateModule) include(mitkMacroCheckModule) include(mitkMacroCreateModuleTests) include(mitkFunctionAddCustomModuleTest) include(mitkMacroUseModule) include(mitkMacroMultiplexPicType) include(mitkMacroInstall) include(mitkMacroInstallHelperApp) include(mitkMacroInstallTargets) include(mitkMacroGenerateToolsLibrary) include(mitkMacroGetLinuxDistribution) #----------------------------------------------------------------------------- # Prerequesites #----------------------------------------------------------------------------- find_package(ITK REQUIRED) find_package(VTK REQUIRED) if(ITK_USE_SYSTEM_GDCM) find_package(GDCM PATHS ${ITK_GDCM_DIR} REQUIRED) endif() #----------------------------------------------------------------------------- # Set MITK specific options and variables (NOT available during superbuild) #----------------------------------------------------------------------------- # ASK THE USER TO SHOW THE CONSOLE WINDOW FOR CoreApp and mitkWorkbench option(MITK_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting MITK GUI Applications" ON) mark_as_advanced(MITK_SHOW_CONSOLE_WINDOW) # TODO: check if necessary option(USE_ITKZLIB "Use the ITK zlib for pic compression." ON) mark_as_advanced(USE_ITKZLIB) if(NOT MITK_FAST_TESTING) if(DEFINED MITK_CTEST_SCRIPT_MODE AND (MITK_CTEST_SCRIPT_MODE STREQUAL "continuous" OR MITK_CTEST_SCRIPT_MODE STREQUAL "experimental") ) set(MITK_FAST_TESTING 1) endif() endif() #----------------------------------------------------------------------------- # Get MITK version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${MITK_SOURCE_DIR} MITK) mitkFunctionGetVersionDescription(${MITK_SOURCE_DIR} MITK) #----------------------------------------------------------------------------- # Installation preparation # # These should be set before any MITK install macros are used #----------------------------------------------------------------------------- # on Mac OSX all BlueBerry plugins get copied into every # application bundle (.app directory) specified here if(MITK_USE_BLUEBERRY AND APPLE) include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) list(GET target_info_list 0 app_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) set(MACOSX_BUNDLE_NAMES ${MACOSX_BUNDLE_NAMES} ${app_name}) endif() endforeach() endif() #----------------------------------------------------------------------------- # Set symbol visibility Flags #----------------------------------------------------------------------------- # MinGW does not export all symbols automatically, so no need to set flags if(CMAKE_COMPILER_IS_GNUCXX AND NOT MINGW) set(VISIBILITY_CXX_FLAGS ) #"-fvisibility=hidden -fvisibility-inlines-hidden") endif() #----------------------------------------------------------------------------- # Set coverage Flags #----------------------------------------------------------------------------- if(WITH_COVERAGE) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG") set(COVERAGE_CXX_FLAGS ${coverage_flags}) set(COVERAGE_C_FLAGS ${coverage_flags}) endif() endif() #----------------------------------------------------------------------------- # MITK C/CXX Flags #----------------------------------------------------------------------------- set(MITK_C_FLAGS "${COVERAGE_C_FLAGS} ${ADDITIONAL_C_FLAGS}") set(MITK_CXX_FLAGS "${VISIBILITY_CXX_FLAGS} ${COVERAGE_CXX_FLAGS} ${ADDITIONAL_CXX_FLAGS}") include(mitkSetupC++0xVariables) set(cflags ) if(WIN32) set(cflags "${cflags} -DPOCO_NO_UNWINDOWS -DWIN32_LEAN_AND_MEAN") endif() +if(NOT MSVC_VERSION) + foreach(_flag + -Wall + -Wextra + -Wpointer-arith + -Winvalid-pch + -Wcast-align + -Wwrite-strings + -Wno-gnu + -fdiagnostics-show-option + ) + mitkFunctionCheckCompilerFlags(${_flag} cflags) + endforeach() +endif() if(CMAKE_COMPILER_IS_GNUCXX) - set(cflags "${cflags} -Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings") - mitkFunctionCheckCompilerFlags("-fdiagnostics-show-option" cflags) mitkFunctionCheckCompilerFlags("-Wl,--no-undefined" cflags) mitkFunctionCheckCompilerFlags("-Wl,--as-needed" cflags) if(MITK_USE_C++0x) mitkFunctionCheckCompilerFlags("-std=c++0x" MITK_CXX_FLAGS) endif() mitkFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION) # With older version of gcc supporting the flag -fstack-protector-all, an extra dependency to libssp.so # is introduced. If gcc is smaller than 4.4.0 and the build type is Release let's not include the flag. # Doing so should allow to build package made for distribution using older linux distro. if(${GCC_VERSION} VERSION_GREATER "4.4.0" OR (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ${GCC_VERSION} VERSION_LESS "4.4.0")) mitkFunctionCheckCompilerFlags("-fstack-protector-all" cflags) endif() if(MINGW) # suppress warnings about auto imported symbols set(MITK_CXX_FLAGS "-Wl,--enable-auto-import ${MITK_CXX_FLAGS}") # we need to define a Windows version set(MITK_CXX_FLAGS "-D_WIN32_WINNT=0x0500 ${MITK_CXX_FLAGS}") endif() #set(MITK_CXX_FLAGS "-Woverloaded-virtual -Wold-style-cast -Wstrict-null-sentinel -Wsign-promo ${MITK_CXX_FLAGS}") set(MITK_CXX_FLAGS "-Woverloaded-virtual -Wstrict-null-sentinel ${MITK_CXX_FLAGS}") set(MITK_CXX_FLAGS_RELEASE "-D_FORTIFY_SOURCE=2 ${MITK_CXX_FLAGS_RELEASE}") endif() set(MITK_C_FLAGS "${cflags} ${MITK_C_FLAGS}") set(MITK_CXX_FLAGS "${cflags} ${MITK_CXX_FLAGS}") #----------------------------------------------------------------------------- # MITK Packages #----------------------------------------------------------------------------- set(MITK_MODULES_PACKAGE_DEPENDS_DIR ${MITK_SOURCE_DIR}/CMake/PackageDepends) set(MODULES_PACKAGE_DEPENDS_DIRS ${MITK_MODULES_PACKAGE_DEPENDS_DIR}) #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) enable_testing() include(CTest) mark_as_advanced(TCL_TCLSH DART_ROOT) option(MITK_ENABLE_GUI_TESTING OFF "Enable the MITK GUI tests") # Setup file for setting custom ctest vars configure_file( CMake/CTestCustom.cmake.in ${MITK_BINARY_DIR}/CTestCustom.cmake @ONLY ) # Configuration for the CMake-generated test driver set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include ") set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN " try {") set(CMAKE_TESTDRIVER_AFTER_TESTMAIN " } catch( std::exception & excp ) { fprintf(stderr,\"%s\\n\",excp.what()); return EXIT_FAILURE; } catch( ... ) { printf(\"Exception caught in the test driver\\n\"); return EXIT_FAILURE; } ") set(MITK_TEST_OUTPUT_DIR "${MITK_BINARY_DIR}/test_output") if(NOT EXISTS ${MITK_TEST_OUTPUT_DIR}) file(MAKE_DIRECTORY ${MITK_TEST_OUTPUT_DIR}) endif() # Test the external project template if(MITK_USE_BLUEBERRY) include(mitkTestProjectTemplate) endif() # Test the package target include(mitkPackageTest) endif() configure_file(mitkTestingConfig.h.in ${MITK_BINARY_DIR}/mitkTestingConfig.h) #----------------------------------------------------------------------------- # MITK_SUPERBUILD_BINARY_DIR #----------------------------------------------------------------------------- # If MITK_SUPERBUILD_BINARY_DIR isn't defined, it means MITK is *NOT* build using Superbuild. # In that specific case, MITK_SUPERBUILD_BINARY_DIR should default to MITK_BINARY_DIR if(NOT DEFINED MITK_SUPERBUILD_BINARY_DIR) set(MITK_SUPERBUILD_BINARY_DIR ${MITK_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # Compile Utilities and set-up MITK variables #----------------------------------------------------------------------------- include(mitkSetupVariables) #----------------------------------------------------------------------------- # Cleanup #----------------------------------------------------------------------------- file(GLOB _MODULES_CONF_FILES ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}/*.cmake) if(_MODULES_CONF_FILES) file(REMOVE ${_MODULES_CONF_FILES}) endif() add_subdirectory(Utilities) if(MITK_USE_BLUEBERRY) # We need to hack a little bit because MITK applications may need # to enable certain BlueBerry plug-ins. However, these plug-ins # are validated separately from the MITK plug-ins and know nothing # about potential MITK plug-in dependencies of the applications. Hence # we cannot pass the MITK application list to the BlueBerry # ctkMacroSetupPlugins call but need to extract the BlueBerry dependencies # from the applications and set them explicitly. include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") foreach(mitk_app ${MITK_APPS}) # extract target_dir and option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 target_dir) list(GET target_info_list 1 option_name) # check if the application is enabled and if target_libraries.cmake exists if((${option_name} OR MITK_BUILD_ALL_APPS) AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/target_libraries.cmake") foreach(_target_dep ${target_libraries}) if(_target_dep MATCHES org_blueberry_) string(REPLACE _ . _app_bb_dep ${_target_dep}) # explicitly set the build option for the BlueBerry plug-in set(BLUEBERRY_BUILD_${_app_bb_dep} ON CACHE BOOL "Build the ${_app_bb_dep} plug-in") endif() endforeach() endif() endforeach() set(mbilog_DIR "${mbilog_BINARY_DIR}") if(MITK_BUILD_ALL_PLUGINS) set(BLUEBERRY_BUILD_ALL_PLUGINS ON) endif() + set(BLUEBERRY_XPDOC_OUTPUT_DIR ${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html/) + add_subdirectory(BlueBerry) set(BlueBerry_DIR ${CMAKE_CURRENT_BINARY_DIR}/BlueBerry CACHE PATH "The directory containing a CMake configuration file for BlueBerry" FORCE) include(mitkMacroCreateCTKPlugin) endif() #----------------------------------------------------------------------------- # Set C/CXX Flags for MITK code #----------------------------------------------------------------------------- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MITK_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${MITK_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MITK_C_FLAGS}") if(MITK_USE_QT) add_definitions(-DQWT_DLL) endif() #----------------------------------------------------------------------------- # Add custom targets representing CDash subprojects #----------------------------------------------------------------------------- foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) if(NOT TARGET ${subproject} AND NOT subproject MATCHES "Unlabeled") add_custom_target(${subproject}) endif() endforeach() #----------------------------------------------------------------------------- # Add subdirectories #----------------------------------------------------------------------------- link_directories(${MITK_LINK_DIRECTORIES}) add_subdirectory(Core) include(${CMAKE_CURRENT_BINARY_DIR}/Core/Code/CppMicroServices/CppMicroServicesConfig.cmake) add_subdirectory(Modules) if(MITK_USE_BLUEBERRY) find_package(BlueBerry REQUIRED) set(MITK_DEFAULT_SUBPROJECTS MITK-Plugins) # Plug-in testing (needs some work to be enabled again) if(BUILD_TESTING) include(berryTestingHelpers) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp") get_target_property(_is_macosx_bundle CoreApp MACOSX_BUNDLE) if(APPLE AND _is_macosx_bundle) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp.app/Contents/MacOS/CoreApp") endif() set(BLUEBERRY_TEST_APP_ID "org.mitk.qt.coreapplication") endif() include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") set(mitk_plugins_fullpath ) foreach(mitk_plugin ${MITK_EXT_PLUGINS}) list(APPEND mitk_plugins_fullpath Plugins/${mitk_plugin}) endforeach() if(EXISTS ${MITK_PRIVATE_MODULES}/PluginList.cmake) include(${MITK_PRIVATE_MODULES}/PluginList.cmake) foreach(mitk_plugin ${MITK_PRIVATE_PLUGINS}) list(APPEND mitk_plugins_fullpath ${MITK_PRIVATE_MODULES}/${mitk_plugin}) endforeach() endif() # Specify which plug-ins belong to this project macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin_mitk "^org_mitk_[a-zA-Z0-9_]+$") set(re_ctkplugin_bb "^org_blueberry_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin_mitk re_ctkplugin_bb OUTPUT_VARIABLE ${varname}) endmacro() # Get infos about application directories and build options include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") set(mitk_apps_fullpath ) foreach(mitk_app ${MITK_APPS}) list(APPEND mitk_apps_fullpath "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${mitk_app}") endforeach() ctkMacroSetupPlugins(${mitk_plugins_fullpath} BUILD_OPTION_PREFIX MITK_BUILD_ APPS ${mitk_apps_fullpath} BUILD_ALL ${MITK_BUILD_ALL_PLUGINS} COMPACT_OPTIONS) set(MITK_PLUGIN_USE_FILE "${MITK_BINARY_DIR}/MitkPluginUseFile.cmake") if(${PROJECT_NAME}_PLUGIN_LIBRARIES) ctkFunctionGeneratePluginUseFile(${MITK_PLUGIN_USE_FILE}) else() file(REMOVE ${MITK_PLUGIN_USE_FILE}) set(MITK_PLUGIN_USE_FILE ) endif() endif() # Construct a list of paths containing runtime directories # for MITK applications on Windows set(MITK_RUNTIME_PATH "${VTK_LIBRARY_DIRS}/%VS_BUILD_TYPE%;${ITK_LIBRARY_DIRS}/%VS_BUILD_TYPE%;${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/%VS_BUILD_TYPE%" ) if(QT4_FOUND) set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${QT_LIBRARY_DIR}/../bin") endif() if(MITK_USE_BLUEBERRY) set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${CTK_RUNTIME_LIBRARY_DIRS}/%VS_BUILD_TYPE%") if(DEFINED CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY) if(IS_ABSOLUTE "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}/%VS_BUILD_TYPE%") else() set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}/%VS_BUILD_TYPE%") endif() else() set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins/%VS_BUILD_TYPE%") endif() endif() if(GDCM_DIR) set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${GDCM_DIR}/bin/%VS_BUILD_TYPE%") endif() if(OpenCV_DIR) set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${OpenCV_DIR}/bin/%VS_BUILD_TYPE%") endif() if(SOFA_DIR) set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${SOFA_DIR}/bin/%VS_BUILD_TYPE%") endif() # DCMTK is statically build #if(DCMTK_DIR) # set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${DCMTK_DIR}/bin/%VS_BUILD_TYPE%") #endif() if(MITK_USE_Boost AND MITK_USE_Boost_LIBRARIES AND NOT MITK_USE_SYSTEM_Boost) set(MITK_RUNTIME_PATH "${MITK_RUNTIME_PATH};${Boost_LIBRARY_DIRS}") endif() #----------------------------------------------------------------------------- # Python Wrapping #----------------------------------------------------------------------------- set(MITK_WRAPPING_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Wrapping) set(MITK_WRAPPING_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/Wrapping) option(MITK_USE_Python "Build cswig Python wrapper support (requires CableSwig)." OFF) if(MITK_USE_Python) add_subdirectory(Wrapping) endif() #----------------------------------------------------------------------------- # Documentation #----------------------------------------------------------------------------- add_subdirectory(Documentation) #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables # These are the default variables, which can be overwritten ( see below ) include(mitkSetupCPack) set(use_default_config ON) # MITK_APPS is set in Applications/AppList.cmake (included somewhere above # if MITK_USE_BLUEBERRY is set to ON). if(MITK_APPS) set(activated_apps_no 0) list(LENGTH MITK_APPS app_count) # Check how many apps have been enabled # If more than one app has been activated, the we use the # default CPack configuration. Otherwise that apps configuration # will be used, if present. foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) MATH(EXPR activated_apps_no "${activated_apps_no} + 1") endif() endforeach() if(app_count EQUAL 1 AND (activated_apps_no EQUAL 1 OR MITK_BUILD_ALL_APPS)) # Corner case if there is only one app in total set(use_project_cpack ON) elseif(activated_apps_no EQUAL 1 AND NOT MITK_BUILD_ALL_APPS) # Only one app is enabled (no "build all" flag set) set(use_project_cpack ON) else() # Less or more then one app is enabled set(use_project_cpack OFF) endif() foreach(mitk_app ${MITK_APPS}) # extract target_dir and option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 target_dir) list(GET target_info_list 1 option_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) # check whether application specific configuration files will be used if(use_project_cpack) # use files if they exist if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") endif() if(EXISTS "${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in") set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/Applications/${target_dir}/CPackConfig.cmake") configure_file(${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in ${CPACK_PROJECT_CONFIG_FILE} @ONLY) set(use_default_config OFF) endif() endif() # add link to the list list(APPEND CPACK_CREATE_DESKTOP_LINKS "${target_dir}") endif() endforeach() endif() # if no application specific configuration file was used, use default if(use_default_config) configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in ${MITK_BINARY_DIR}/MITKCPackOptions.cmake @ONLY) set(CPACK_PROJECT_CONFIG_FILE "${MITK_BINARY_DIR}/MITKCPackOptions.cmake") endif() # include CPack model once all variables are set include(CPack) # Additional installation rules include(mitkInstallRules) #----------------------------------------------------------------------------- # Last configuration steps #----------------------------------------------------------------------------- # This is for installation support of external projects depending on # MITK plugins and modules. The export file should not be used for linking to MITK # libraries without using LINK_DIRECTORIES, since the exports are incomplete # yet (depending libraries are not exported). set(MITK_EXPORTS_FILE "${MITK_BINARY_DIR}/MitkExports.cmake") file(REMOVE ${MITK_EXPORTS_FILE}) set(targets_to_export) get_property(module_targets GLOBAL PROPERTY MITK_MODULE_TARGETS) if(module_targets) list(APPEND targets_to_export ${module_targets}) endif() if(MITK_USE_BLUEBERRY) if(MITK_PLUGIN_LIBRARIES) list(APPEND targets_to_export ${MITK_PLUGIN_LIBRARIES}) endif() endif() export(TARGETS ${targets_to_export} APPEND FILE ${MITK_EXPORTS_FILE}) set(MITK_EXPORTED_TARGET_PROPERTIES ) foreach(target_to_export ${targets_to_export}) get_target_property(autoload_targets ${target_to_export} MITK_AUTOLOAD_TARGETS) if(autoload_targets) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_TARGETS \"${autoload_targets}\")") endif() get_target_property(autoload_dir ${target_to_export} MITK_AUTOLOAD_DIRECTORY) if(autoload_dir) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_DIRECTORY \"${autoload_dir}\")") endif() endforeach() configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactory.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactoryLoader.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactoryLoader.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolGUIExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolGUIExtensionITKFactory.cpp.in COPYONLY) set(VISIBILITY_AVAILABLE 0) set(visibility_test_flag "") mitkFunctionCheckCompilerFlags("-fvisibility=hidden" visibility_test_flag) if(visibility_test_flag) # The compiler understands -fvisiblity=hidden (probably gcc >= 4 or Clang) set(VISIBILITY_AVAILABLE 1) endif() configure_file(mitkExportMacros.h.in ${MITK_BINARY_DIR}/mitkExportMacros.h) configure_file(mitkVersion.h.in ${MITK_BINARY_DIR}/mitkVersion.h) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) set(VECMATH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/vecmath) set(IPFUNC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipFunc) set(UTILITIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities) file(GLOB _MODULES_CONF_FILES RELATIVE ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME} ${PROJECT_BINARY_DIR}/${MODULES_CONF_DIRNAME}/*.cmake) set(MITK_MODULE_NAMES) foreach(_module ${_MODULES_CONF_FILES}) string(REPLACE Config.cmake "" _module_name ${_module}) list(APPEND MITK_MODULE_NAMES ${_module_name}) endforeach() configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) configure_file(MITKConfig.cmake.in ${MITK_BINARY_DIR}/MITKConfig.cmake @ONLY) # If we are under Windows, create two batch files which correctly # set up the environment for the application and for Visual Studio if(WIN32) include(mitkFunctionCreateWindowsBatchScript) set(VS_SOLUTION_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.sln") foreach(VS_BUILD_TYPE debug release) mitkFunctionCreateWindowsBatchScript("${MITK_SOURCE_DIR}/CMake/StartVS.bat.in" ${PROJECT_BINARY_DIR}/StartVS_${VS_BUILD_TYPE}.bat ${VS_BUILD_TYPE}) endforeach() endif(WIN32) #----------------------------------------------------------------------------- # MITK Applications #----------------------------------------------------------------------------- # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Applications) #----------------------------------------------------------------------------- # MITK Examples #----------------------------------------------------------------------------- if(MITK_BUILD_EXAMPLES) # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Examples) endif() diff --git a/Core/Code/CppMicroServices/CMake/usCTestScript.cmake b/Core/Code/CppMicroServices/CMake/usCTestScript.cmake index af6ee829a7..7feac62e8e 100644 --- a/Core/Code/CppMicroServices/CMake/usCTestScript.cmake +++ b/Core/Code/CppMicroServices/CMake/usCTestScript.cmake @@ -1,131 +1,131 @@ macro(build_and_test) set(CTEST_SOURCE_DIRECTORY ${US_SOURCE_DIR}) set(CTEST_BINARY_DIRECTORY "${CTEST_DASHBOARD_ROOT}/${CTEST_PROJECT_NAME}_${CTEST_DASHBOARD_NAME}") #if(NOT CTEST_BUILD_NAME) # set(CTEST_BUILD_NAME "${CMAKE_SYSTEM}_${CTEST_COMPILER}_${CTEST_DASHBOARD_NAME}") #endif() ctest_empty_binary_directory(${CTEST_BINARY_DIRECTORY}) ctest_start("Experimental") if(NOT EXISTS "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt") file(WRITE "${CTEST_BINARY_DIRECTORY}/CMakeCache.txt" "${CTEST_INITIAL_CACHE}") endif() ctest_configure(RETURN_VALUE res) if (res) message(FATAL_ERROR "CMake configure error") endif() ctest_build(RETURN_VALUE res) if (res) message(FATAL_ERROR "CMake build error") endif() ctest_test(RETURN_VALUE res PARALLEL_LEVEL ${CTEST_PARALLEL_LEVEL}) if (res) message(FATAL_ERROR "CMake test error") endif() if(WITH_MEMCHECK AND CTEST_MEMORYCHECK_COMMAND) ctest_memcheck() endif() if(WITH_COVERAGE AND CTEST_COVERAGE_COMMAND) ctest_coverage() endif() #ctest_submit() endmacro() -function(create_initial_cache var _shared _threading _sf _c++11 _autoload) +function(create_initial_cache var _shared _threading _sf _cxx11 _autoload) set(_initial_cache " US_BUILD_TESTING:BOOL=ON US_BUILD_SHARED_LIBS:BOOL=${_shared} US_ENABLE_THREADING_SUPPORT:BOOL=${_threading} US_ENABLE_SERVICE_FACTORY_SUPPORT:BOOL=${_sf} - US_USE_C++11:BOOL=${_c++11} + US_USE_C++11:BOOL=${_cxx11} US_ENABLE_AUTOLOADING_SUPPORT:BOOL=${_autoload} ") set(${var} ${_initial_cache} PARENT_SCOPE) if(_shared) set(CTEST_DASHBOARD_NAME "shared") else() set(CTEST_DASHBOARD_NAME "static") endif() if(_threading) set(CTEST_DASHBOARD_NAME "${CTEST_DASHBOARD_NAME}-threading") endif() if(_sf) set(CTEST_DASHBOARD_NAME "${CTEST_DASHBOARD_NAME}-servicefactory") endif() - if(_c++11) + if(_cxx11) set(CTEST_DASHBOARD_NAME "${CTEST_DASHBOARD_NAME}-cxx11") endif() if(_autoload) set(CTEST_DASHBOARD_NAME "${CTEST_DASHBOARD_NAME}-autoloading") endif() set(CTEST_DASHBOARD_NAME ${CTEST_DASHBOARD_NAME} PARENT_SCOPE) endfunction() #========================================================= set(CTEST_PROJECT_NAME CppMicroServices) if(NOT CTEST_PARALLEL_LEVEL) set(CTEST_PARALLEL_LEVEL 1) endif() # SHARED THREADING SERVICE_FACTORY C++11 AUTOLOAD set(config0 0 0 0 0 0 ) set(config1 0 0 0 0 1 ) set(config2 0 0 0 1 0 ) set(config3 0 0 0 1 1 ) set(config4 0 0 1 0 0 ) set(config5 0 0 1 0 1 ) set(config6 0 0 1 1 0 ) set(config7 0 0 1 1 1 ) set(config8 0 1 0 0 0 ) set(config9 0 1 0 0 1 ) set(config10 0 1 0 1 0 ) set(config11 0 1 0 1 1 ) set(config12 0 1 1 0 0 ) set(config13 0 1 1 0 1 ) set(config14 0 1 1 1 0 ) set(config15 0 1 1 1 1 ) set(config16 1 0 0 0 0 ) set(config17 1 0 0 0 1 ) set(config18 1 0 0 1 0 ) set(config19 1 0 0 1 1 ) set(config20 1 0 1 0 0 ) set(config21 1 0 1 0 1 ) set(config22 1 0 1 1 0 ) set(config23 1 0 1 1 1 ) set(config24 1 1 0 0 0 ) set(config25 1 1 0 0 1 ) set(config26 1 1 0 1 0 ) set(config27 1 1 0 1 1 ) set(config28 1 1 1 0 0 ) set(config29 1 1 1 0 1 ) set(config30 1 1 1 1 0 ) set(config31 1 1 1 1 1 ) foreach(i ${US_BUILD_CONFIGURATION}) create_initial_cache(CTEST_INITIAL_CACHE ${config${i}}) message("Testing build configuration: ${CTEST_DASHBOARD_NAME}") build_and_test() endforeach() diff --git a/Core/Code/CppMicroServices/CMakeLists.txt b/Core/Code/CppMicroServices/CMakeLists.txt index 502194688a..be5a542de2 100644 --- a/Core/Code/CppMicroServices/CMakeLists.txt +++ b/Core/Code/CppMicroServices/CMakeLists.txt @@ -1,357 +1,358 @@ project(CppMicroServices) set(${PROJECT_NAME}_MAJOR_VERSION 0) set(${PROJECT_NAME}_MINOR_VERSION 99) set(${PROJECT_NAME}_PATCH_VERSION 0) set(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_MAJOR_VERSION}.${${PROJECT_NAME}_MINOR_VERSION}.${${PROJECT_NAME}_PATCH_VERSION}) cmake_minimum_required(VERSION 2.8) #----------------------------------------------------------------------------- # Update CMake module path #------------------------------------------------------------------------------ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(MacroParseArguments) include(CheckCXXSourceCompiles) include(usFunctionCheckCompilerFlags) include(usFunctionEmbedResources) include(usFunctionGetGccVersion) include(usFunctionGenerateModuleInit) #----------------------------------------------------------------------------- # Init output directories #----------------------------------------------------------------------------- set(US_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") set(US_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") set(US_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") foreach(_type ARCHIVE LIBRARY RUNTIME) if(NOT CMAKE_${_type}_OUTPUT_DIRECTORY) set(CMAKE_${_type}_OUTPUT_DIRECTORY ${US_${_type}_OUTPUT_DIRECTORY}) endif() endforeach() #----------------------------------------------------------------------------- # Set a default build type if none was specified #----------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Debug' as none was specified.") set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() #----------------------------------------------------------------------------- # CMake options #----------------------------------------------------------------------------- function(us_cache_var _var_name _var_default _var_type _var_help) set(_advanced 0) set(_force) foreach(_argn ${ARGN}) if(_argn STREQUAL ADVANCED) set(_advanced 1) elseif(_argn STREQUAL FORCE) set(_force FORCE) endif() endforeach() if(US_IS_EMBEDDED) if(NOT DEFINED ${_var_name} OR _force) set(${_var_name} ${_var_default} PARENT_SCOPE) endif() else() set(${_var_name} ${_var_default} CACHE ${_var_type} "${_var_help}" ${_force}) if(_advanced) mark_as_advanced(${_var_name}) endif() endif() endfunction() # Determine if we are being build inside a larger project if(NOT DEFINED US_IS_EMBEDDED) if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) set(US_IS_EMBEDDED 0) else() set(US_IS_EMBEDDED 1) set(CppMicroServices_EXPORTS 1) endif() endif() us_cache_var(US_ENABLE_AUTOLOADING_SUPPORT OFF BOOL "Enable module auto-loading support") us_cache_var(US_ENABLE_SERVICE_FACTORY_SUPPORT ON BOOL "Enable Service Factory support" ADVANCED) us_cache_var(US_ENABLE_THREADING_SUPPORT OFF BOOL "Enable threading support") +us_cache_var(US_ENABLE_DEBUG_OUTPUT OFF BOOL "Enable debug messages" ADVANCED) us_cache_var(US_BUILD_SHARED_LIBS ON BOOL "Build shared libraries") us_cache_var(US_BUILD_TESTING OFF BOOL "Build tests") if(MSVC10 OR MSVC11) # Visual Studio 2010 and newer have support for C++11 enabled by default set(US_USE_C++11 1) else() us_cache_var(US_USE_C++11 OFF BOOL "Enable the use of C++11 features" ADVANCED) endif() us_cache_var(US_NAMESPACE "us" STRING "The namespace for the C++ micro services entities") us_cache_var(US_HEADER_PREFIX "" STRING "The file name prefix for the public C++ micro services header files") us_cache_var(US_BASECLASS_NAME "" STRING "The fully-qualified name of the base class") if(US_ENABLE_SERVICE_FACTORY_SUPPORT) us_cache_var(US_BASECLASS_PACKAGE "" STRING "The name of the package providing the base class definition" ADVANCED) set(bc_inc_d_doc "A list of include directories containing the header files for the base class") us_cache_var(US_BASECLASS_INCLUDE_DIRS "" STRING "${bc_inc_d_doc}" ADVANCED) set(bc_lib_d_doc "A list of library directories for the base class") us_cache_var(US_BASECLASS_LIBRARY_DIRS "" STRING "${bc_lib_d_doc}" ADVANCED) set(bc_lib_doc "A list of libraries needed for the base class") us_cache_var(US_BASECLASS_LIBRARIES "" STRING "${bc_lib_doc}" ADVANCED) us_cache_var(US_BASECLASS_HEADER "" STRING "The name of the header file containing the base class declaration" ADVANCED) endif() set(BUILD_SHARED_LIBS ${US_BUILD_SHARED_LIBS}) # Sanity checks if(US_ENABLE_SERVICE_FACTORY_SUPPORT OR US_BUILD_TESTING) if(US_BASECLASS_PACKAGE) find_package(${US_BASECLASS_PACKAGE} REQUIRED) # Try to get the include dirs foreach(_suffix DIRECTORIES DIRS DIRECTORY DIR) if(${US_BASECLASS_PACKAGE}_INCLUDE_${_suffix} AND NOT US_BASECLASS_INCLUDE_DIRS) us_cache_var(US_BASECLASS_INCLUDE_DIRS "${${US_BASECLASS_PACKAGE}_INCLUDE_${_suffix}}" STRING "${bc_inc_d_doc}" FORCE) break() endif() endforeach() # Try to get the library dirs foreach(_suffix DIRECTORIES DIRS DIRECTORY DIR) if(${US_BASECLASS_PACKAGE}_LIBRARY_${_suffix} AND NOT US_BASECLASS_LIBRARY_DIRS) us_cache_var(US_BASECLASS_LIBRARY_DIRS "${${US_BASECLASS_PACKAGE}_LIBRARY_${_suffix}}" STRING "${bc_lib_d_doc}" FORCE) break() endif() endforeach() # Try to get the libraries foreach(_suffix LIBRARIES LIBS LIBRARY LIB) if(${US_BASECLASS_PACKAGE}_${_suffix} AND NOT US_BASECLASS_LIBRARIES) us_cache_var(US_BASECLASS_LIBRARIES "${${US_BASECLASS_PACKAGE}_${_suffix}}" STRING "${bc_lib_doc}" FORCE) break() endif() endforeach() if(NOT US_BASECLASS_NAME) message(FATAL_ERROR "US_BASECLASS_NAME not set") elseif(NOT US_BASECLASS_HEADER) message(FATAL_ERROR "US_BASECLASS_HEADER not set") endif() endif() if(US_ENABLE_SERVICE_FACTORY_SUPPORT AND US_BASECLASS_NAME AND NOT US_BASECLASS_HEADER) message(FATAL_ERROR "US_ENABLE_SERVICE_FACTORY_SUPPORT requires a US_BASECLASS_HEADER value") endif() endif() set(_us_baseclass_default 0) if(NOT US_BASECLASS_NAME) message(WARNING "Using build in base class \"::${US_NAMESPACE}::Base\"") set(_us_baseclass_default 1) set(US_BASECLASS_NAME "${US_NAMESPACE}::Base") set(US_BASECLASS_HEADER "usBase.h") endif() if(US_BUILD_TESTING AND US_BASECLASS_NAME AND NOT US_BASECLASS_HEADER) message(FATAL_ERROR "US_BUILD_TESTING requires a US_BASECLASS_HEADER value") endif() set(US_BASECLASS_INCLUDE "#include <${US_BASECLASS_HEADER}>") string(REPLACE "::" ";" _bc_token "${US_BASECLASS_NAME}") list(GET _bc_token -1 _bc_name) list(REMOVE_AT _bc_token -1) set(US_BASECLASS_FORWARD_DECLARATION "") foreach(_namespace_tok ${_bc_token}) if(_namespace_tok) set(US_BASECLASS_FORWARD_DECLARATION "${US_BASECLASS_FORWARD_DECLARATION}namespace ${_namespace_tok} { ") endif() endforeach() set(US_BASECLASS_FORWARD_DECLARATION "${US_BASECLASS_FORWARD_DECLARATION}class ${_bc_name}; ") foreach(_namespace_tok ${_bc_token}) if(_namespace_tok) set(US_BASECLASS_FORWARD_DECLARATION "${US_BASECLASS_FORWARD_DECLARATION}}") endif() endforeach() #----------------------------------------------------------------------------- # US C/CXX Flags #----------------------------------------------------------------------------- set(US_C_FLAGS "${COVERAGE_C_FLAGS} ${ADDITIONAL_C_FLAGS}") set(US_CXX_FLAGS "${COVERAGE_CXX_FLAGS} ${ADDITIONAL_CXX_FLAGS}") # This is used as a preprocessor define set(US_USE_CXX11 ${US_USE_C++11}) # Set C++ compiler flags if(NOT MSVC) foreach(_cxxflag -Werror -Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings -Woverloaded-virtual -Wnon-virtual-dtor -Wold-style-cast -Wstrict-null-sentinel -Wsign-promo -fdiagnostics-show-option -D_FORTIFY_SOURCE=2) usFunctionCheckCompilerFlags(${_cxxflag} US_CXX_FLAGS) endforeach() if(US_USE_C++11) usFunctionCheckCompilerFlags("-std=c++0x" US_CXX_FLAGS) endif() endif() if(CMAKE_COMPILER_IS_GNUCXX) usFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION) # With older versions of gcc the flag -fstack-protector-all requires an extra dependency to libssp.so. # If the gcc version is lower than 4.4.0 and the build type is Release let's not include the flag. if(${GCC_VERSION} VERSION_GREATER "4.4.0" OR (CMAKE_BUILD_TYPE STREQUAL "Debug" AND ${GCC_VERSION} VERSION_LESS "4.4.0")) usFunctionCheckCompilerFlags("-fstack-protector-all" US_CXX_FLAGS) endif() if(MINGW) # suppress warnings about auto imported symbols set(US_CXX_FLAGS "-Wl,--enable-auto-import ${US_CXX_FLAGS}") # we need to define a Windows version set(US_CXX_FLAGS "-D_WIN32_WINNT=0x0500 ${US_CXX_FLAGS}") else() # Enable visibility support if(NOT ${GCC_VERSION} VERSION_LESS "4.5") usFunctionCheckCompilerFlags("-fvisibility=hidden -fvisibility-inlines-hidden" US_CXX_FLAGS) endif() endif() elseif(MSVC) set(US_CXX_FLAGS "/MP /wd4996 ${US_CXX_FLAGS}") endif() if(NOT US_IS_EMBEDDED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${US_CXX_FLAGS}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${US_C_FLAGS}") endif() #----------------------------------------------------------------------------- # US Link Flags #----------------------------------------------------------------------------- set(US_LINK_FLAGS ) if(NOT MSVC) foreach(_linkflag -Wl,--no-undefined) set(_add_flag) usFunctionCheckCompilerFlags("${_linkflag}" _add_flag) if(_add_flag) set(US_LINK_FLAGS "${US_LINK_FLAGS} ${_linkflag}") endif() endforeach() endif() #----------------------------------------------------------------------------- # US Header Checks #----------------------------------------------------------------------------- include(CheckIncludeFile) CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT) #----------------------------------------------------------------------------- # US include dirs and libraries #----------------------------------------------------------------------------- set(US_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/include ) set(US_INTERNAL_INCLUDE_DIRS ${PROJECT_BINARY_DIR}/include ${CMAKE_CURRENT_SOURCE_DIR}/src/util ${CMAKE_CURRENT_SOURCE_DIR}/src/service ${CMAKE_CURRENT_SOURCE_DIR}/src/module ) if(US_ENABLE_SERVICE_FACTORY_SUPPORT) list(APPEND US_INTERNAL_INCLUDE_DIRS ${US_BASECLASS_INCLUDE_DIRS}) endif() # link libraries for third party libs if(US_IS_EMBEDDED) set(US_LINK_LIBRARIES ${US_EMBEDDING_LIBRARY}) else() set(US_LINK_LIBRARIES ${PROJECT_NAME}) endif() # link libraries for the CppMicroServices lib set(_link_libraries ) if(UNIX) list(APPEND _link_libraries dl) endif() list(APPEND US_LINK_LIBRARIES ${_link_libraries}) if(US_ENABLE_SERVICE_FACTORY_SUPPORT) list(APPEND US_LINK_LIBRARIES ${US_BASECLASS_LIBRARIES}) endif() set(US_LINK_DIRS ) if(US_ENABLE_SERVICE_FACTORY_SUPPORT) list(APPEND US_LINK_DIRS ${US_BASECLASS_LIBRARY_DIRS}) endif() #----------------------------------------------------------------------------- # Source directory #----------------------------------------------------------------------------- set(us_config_h_file "${PROJECT_BINARY_DIR}/include/usConfig.h") configure_file(usConfig.h.in ${us_config_h_file}) set(US_RCC_EXECUTABLE_NAME usResourceCompiler) set(CppMicroServices_RCC_EXECUTABLE_NAME ${US_RCC_EXECUTABLE_NAME}) set(US_RCC_EXECUTABLE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${US_RCC_EXECUTABLE_NAME}") set(CppMicroServices_RCC_EXECUTABLE ${US_RCC_EXECUTABLE}) add_subdirectory(tools) add_subdirectory(src) #----------------------------------------------------------------------------- # US testing #----------------------------------------------------------------------------- if(US_BUILD_TESTING) enable_testing() add_subdirectory(test) endif() #----------------------------------------------------------------------------- # Documentation #----------------------------------------------------------------------------- add_subdirectory(documentation) #----------------------------------------------------------------------------- # Last configuration steps #----------------------------------------------------------------------------- configure_file(${PROJECT_NAME}Config.cmake.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake @ONLY) diff --git a/Core/Code/CppMicroServices/documentation/doxygen/MicroServices_Debugging.dox b/Core/Code/CppMicroServices/documentation/doxygen/MicroServices_Debugging.dox index 9e3c9ed92e..4e3c735c8f 100644 --- a/Core/Code/CppMicroServices/documentation/doxygen/MicroServices_Debugging.dox +++ b/Core/Code/CppMicroServices/documentation/doxygen/MicroServices_Debugging.dox @@ -1,69 +1,70 @@ /** * \ingroup MicroServicesUtils * * \enum MsgType * This enum describes the messages that can be sent to a message handler (MsgHandler). * You can use the enum to identify and associate the various message types with the * appropriate actions. */ - + /** * \ingroup MicroServicesUtils * * \var MsgType DebugMsg * A debug message. */ - + /** * \ingroup MicroServicesUtils * * \var MsgType InfoMsg * An informational message. */ - + /** * \ingroup MicroServicesUtils * * \var MsgType WarningMsg * A warning message. */ - + /** * \ingroup MicroServicesUtils * * \var MsgType ErrorMsg * An error message. */ - + /** * \ingroup MicroServicesUtils * * \typedef MsgHandler * A message handler callback function. */ - + /** * \ingroup MicroServicesUtils * * \fn MsgHandler installMsgHandler(MsgHandler) * \brief Installs a message handler which has been defined previously. * * Returns a pointer to the previous message handler (which may be 0). * * The message handler is a function that prints out debug messages, warnings, * and fatal error messages. The C++ Micro Services library (debug mode) contains * warning messages that are printed when internal errors (usually invalid function * arguments) occur. The library built in release mode also contains such warnings - * unless US_NO_WARNING_OUTPUT and/or US_NO_DEBUG_OUTPUT have been set during - * compilation. If you implement your own message handler, you get total control of - * these messages. + * unless US_NO_WARNING_OUTPUT has been set during compilation. In both debug and release mode + * debugging message are suppressed by default, unless US_ENABLE_DEBUGGING_OUTPUT + * has been set during compilation. If you implement your own message handler, + * you get total control of these messages. * * The default message handler prints the message to the standard output. If it is * an error message, the application aborts immediately. * * Only one message handler can be defined, since this is usually done on an * application-wide basis to control debug output. * * To restore the message handler, call installMsgHandler(0). */ diff --git a/Core/Code/CppMicroServices/src/module/usModuleAbstractTracked.tpp b/Core/Code/CppMicroServices/src/module/usModuleAbstractTracked.tpp index a40324c462..d344538f03 100644 --- a/Core/Code/CppMicroServices/src/module/usModuleAbstractTracked.tpp +++ b/Core/Code/CppMicroServices/src/module/usModuleAbstractTracked.tpp @@ -1,314 +1,314 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include US_BEGIN_NAMESPACE template -const bool ModuleAbstractTracked::DEBUG = false; +const bool ModuleAbstractTracked::DEBUG_OUTPUT = false; template ModuleAbstractTracked::ModuleAbstractTracked() { closed = false; } template ModuleAbstractTracked::~ModuleAbstractTracked() { } template void ModuleAbstractTracked::SetInitial(const std::list& initiallist) { initial = initiallist; - if (DEBUG) + if (DEBUG_OUTPUT) { for(typename std::list::const_iterator item = initiallist.begin(); item != initiallist.end(); ++item) { US_DEBUG << "ModuleAbstractTracked::setInitial: " << (*item); } } } template void ModuleAbstractTracked::TrackInitial() { while (true) { S item(0); { typename Self::Lock l(this); if (closed || (initial.size() == 0)) { /* * if there are no more initial items */ return; /* we are done */ } /* * move the first item from the initial list to the adding list * within this synchronized block. */ item = initial.front(); initial.pop_front(); if (tracked[item]) { /* if we are already tracking this item */ - US_DEBUG(DEBUG) << "ModuleAbstractTracked::trackInitial[already tracked]: " << item; + US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackInitial[already tracked]: " << item; continue; /* skip this item */ } if (std::find(adding.begin(), adding.end(), item) != adding.end()) { /* * if this item is already in the process of being added. */ - US_DEBUG(DEBUG) << "ModuleAbstractTracked::trackInitial[already adding]: " << item; + US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackInitial[already adding]: " << item; continue; /* skip this item */ } adding.push_back(item); } - US_DEBUG(DEBUG) << "ModuleAbstractTracked::trackInitial: " << item; + US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackInitial: " << item; TrackAdding(item, R()); /* * Begin tracking it. We call trackAdding * since we have already put the item in the * adding list. */ } } template void ModuleAbstractTracked::Close() { closed = true; } template void ModuleAbstractTracked::Track(S item, R related) { T object(0); { typename Self::Lock l(this); if (closed) { return; } object = tracked[item]; if (!object) { /* we are not tracking the item */ if (std::find(adding.begin(), adding.end(),item) != adding.end()) { /* if this item is already in the process of being added. */ - US_DEBUG(DEBUG) << "ModuleAbstractTracked::track[already adding]: " << item; + US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::track[already adding]: " << item; return; } adding.push_back(item); /* mark this item is being added */ } else { /* we are currently tracking this item */ - US_DEBUG(DEBUG) << "ModuleAbstractTracked::track[modified]: " << item; + US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::track[modified]: " << item; Modified(); /* increment modification count */ } } if (!object) { /* we are not tracking the item */ TrackAdding(item, related); } else { /* Call customizer outside of synchronized region */ CustomizerModified(item, related, object); /* * If the customizer throws an unchecked exception, it is safe to * let it propagate */ } } template void ModuleAbstractTracked::Untrack(S item, R related) { T object(0); { typename Self::Lock l(this); std::size_t initialSize = initial.size(); initial.remove(item); if (initialSize != initial.size()) { /* if this item is already in the list * of initial references to process */ - US_DEBUG(DEBUG) << "ModuleAbstractTracked::untrack[removed from initial]: " << item; + US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::untrack[removed from initial]: " << item; return; /* we have removed it from the list and it will not be * processed */ } std::size_t addingSize = adding.size(); adding.remove(item); if (addingSize != adding.size()) { /* if the item is in the process of * being added */ - US_DEBUG(DEBUG) << "ModuleAbstractTracked::untrack[being added]: " << item; + US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::untrack[being added]: " << item; return; /* * in case the item is untracked while in the process of * adding */ } object = tracked[item]; /* * must remove from tracker before * calling customizer callback */ tracked.erase(item); if (!object) { /* are we actually tracking the item */ return; } Modified(); /* increment modification count */ } - US_DEBUG(DEBUG) << "ModuleAbstractTracked::untrack[removed]: " << item; + US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::untrack[removed]: " << item; /* Call customizer outside of synchronized region */ CustomizerRemoved(item, related, object); /* * If the customizer throws an unchecked exception, it is safe to let it * propagate */ } template std::size_t ModuleAbstractTracked::Size() const { return tracked.size(); } template bool ModuleAbstractTracked::IsEmpty() const { return tracked.empty(); } template T ModuleAbstractTracked::GetCustomizedObject(S item) const { typename TrackingMap::const_iterator i = tracked.find(item); if (i != tracked.end()) return i->second; return T(); } template void ModuleAbstractTracked::GetTracked(std::list& items) const { for (typename TrackingMap::const_iterator i = tracked.begin(); i != tracked.end(); ++i) { items.push_back(i->first); } } template void ModuleAbstractTracked::Modified() { trackingCount.Ref(); } template int ModuleAbstractTracked::GetTrackingCount() const { return trackingCount; } template void ModuleAbstractTracked::CopyEntries(TrackingMap& map) const { map.insert(tracked.begin(), tracked.end()); } template bool ModuleAbstractTracked::CustomizerAddingFinal(S item, const T& custom) { typename Self::Lock l(this); std::size_t addingSize = adding.size(); adding.remove(item); if (addingSize != adding.size() && !closed) { /* * if the item was not untracked during the customizer * callback */ if (custom) { tracked[item] = custom; Modified(); /* increment modification count */ this->NotifyAll(); /* notify any waiters */ } return false; } else { return true; } } template void ModuleAbstractTracked::TrackAdding(S item, R related) { - US_DEBUG(DEBUG) << "ModuleAbstractTracked::trackAdding:" << item; + US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackAdding:" << item; T object(0); bool becameUntracked = false; /* Call customizer outside of synchronized region */ try { object = CustomizerAdding(item, related); becameUntracked = this->CustomizerAddingFinal(item, object); } catch (...) { /* * If the customizer throws an exception, it will * propagate after the cleanup code. */ this->CustomizerAddingFinal(item, object); throw; } /* * The item became untracked during the customizer callback. */ if (becameUntracked && object) { - US_DEBUG(DEBUG) << "ModuleAbstractTracked::trackAdding[removed]: " << item; + US_DEBUG(DEBUG_OUTPUT) << "ModuleAbstractTracked::trackAdding[removed]: " << item; /* Call customizer outside of synchronized region */ CustomizerRemoved(item, related, object); /* * If the customizer throws an unchecked exception, it is safe to * let it propagate */ } } US_END_NAMESPACE diff --git a/Core/Code/CppMicroServices/src/module/usModuleAbstractTracked_p.h b/Core/Code/CppMicroServices/src/module/usModuleAbstractTracked_p.h index 982c97d99d..ccdc3627d4 100644 --- a/Core/Code/CppMicroServices/src/module/usModuleAbstractTracked_p.h +++ b/Core/Code/CppMicroServices/src/module/usModuleAbstractTracked_p.h @@ -1,291 +1,291 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #ifndef USMODULEABSTRACTTRACKED_H #define USMODULEABSTRACTTRACKED_H #include #include "usAtomicInt_p.h" #include "usAny.h" US_BEGIN_NAMESPACE /** * This class is not intended to be used directly. It is exported to support * the CppMicroServices module system. * * Abstract class to track items. If a Tracker is reused (closed then reopened), * then a new ModuleAbstractTracked object is used. This class acts as a map of tracked * item -> customized object. Subclasses of this class will act as the listener * object for the tracker. This class is used to synchronize access to the * tracked items. This is not a public class. It is only for use by the * implementation of the Tracker class. * * @tparam S The tracked item. It is the key. * @tparam T The value mapped to the tracked item. * @tparam R The reason the tracked item is being tracked or untracked. * @ThreadSafe */ template class ModuleAbstractTracked : public US_DEFAULT_THREADING > { public: /* set this to true to compile in debug messages */ - static const bool DEBUG; // = false; + static const bool DEBUG_OUTPUT; // = false; typedef std::map TrackingMap; /** * ModuleAbstractTracked constructor. */ ModuleAbstractTracked(); virtual ~ModuleAbstractTracked(); /** * Set initial list of items into tracker before events begin to be * received. * * This method must be called from Tracker's open method while synchronized * on this object in the same synchronized block as the add listener call. * * @param list The initial list of items to be tracked. null * entries in the list are ignored. * @GuardedBy this */ void SetInitial(const std::list& list); /** * Track the initial list of items. This is called after events can begin to * be received. * * This method must be called from Tracker's open method while not * synchronized on this object after the add listener call. * */ void TrackInitial(); /** * Called by the owning Tracker object when it is closed. */ void Close(); /** * Begin to track an item. * * @param item S to be tracked. * @param related Action related object. */ void Track(S item, R related); /** * Discontinue tracking the item. * * @param item S to be untracked. * @param related Action related object. */ void Untrack(S item, R related); /** * Returns the number of tracked items. * * @return The number of tracked items. * * @GuardedBy this */ std::size_t Size() const; /** * Returns if the tracker is empty. * * @return Whether the tracker is empty. * * @GuardedBy this */ bool IsEmpty() const; /** * Return the customized object for the specified item * * @param item The item to lookup in the map * @return The customized object for the specified item. * * @GuardedBy this */ T GetCustomizedObject(S item) const; /** * Return the list of tracked items. * * @return The tracked items. * @GuardedBy this */ void GetTracked(std::list& items) const; /** * Increment the modification count. If this method is overridden, the * overriding method MUST call this method to increment the tracking count. * * @GuardedBy this */ virtual void Modified(); /** * Returns the tracking count for this ServiceTracker object. * * The tracking count is initialized to 0 when this object is opened. Every * time an item is added, modified or removed from this object the tracking * count is incremented. * * @GuardedBy this * @return The tracking count for this object. */ int GetTrackingCount() const; /** * Copy the tracked items and associated values into the specified map. * * @param map The map into which to copy the tracked items and associated * values. This map must not be a user provided map so that user code * is not executed while synchronized on this. * @return The specified map. * @GuardedBy this */ void CopyEntries(TrackingMap& map) const; /** * Call the specific customizer adding method. This method must not be * called while synchronized on this object. * * @param item S to be tracked. * @param related Action related object. * @return Customized object for the tracked item or null if * the item is not to be tracked. */ virtual T CustomizerAdding(S item, const R& related) = 0; /** * Call the specific customizer modified method. This method must not be * called while synchronized on this object. * * @param item Tracked item. * @param related Action related object. * @param object Customized object for the tracked item. */ virtual void CustomizerModified(S item, const R& related, T object) = 0; /** * Call the specific customizer removed method. This method must not be * called while synchronized on this object. * * @param item Tracked item. * @param related Action related object. * @param object Customized object for the tracked item. */ virtual void CustomizerRemoved(S item, const R& related, T object) = 0; /** * List of items in the process of being added. This is used to deal with * nesting of events. Since events may be synchronously delivered, events * can be nested. For example, when processing the adding of a service and * the customizer causes the service to be unregistered, notification to the * nested call to untrack that the service was unregistered can be made to * the track method. * * Since the std::vector implementation is not synchronized, all access to * this list must be protected by the same synchronized object for * thread-safety. * * @GuardedBy this */ std::list adding; /** * true if the tracked object is closed. * * This field is volatile because it is set by one thread and read by * another. */ volatile bool closed; /** * Initial list of items for the tracker. This is used to correctly process * the initial items which could be modified before they are tracked. This * is necessary since the initial set of tracked items are not "announced" * by events and therefore the event which makes the item untracked could be * delivered before we track the item. * * An item must not be in both the initial and adding lists at the same * time. An item must be moved from the initial list to the adding list * "atomically" before we begin tracking it. * * Since the LinkedList implementation is not synchronized, all access to * this list must be protected by the same synchronized object for * thread-safety. * * @GuardedBy this */ std::list initial; /** * Common logic to add an item to the tracker used by track and * trackInitial. The specified item must have been placed in the adding list * before calling this method. * * @param item S to be tracked. * @param related Action related object. */ void TrackAdding(S item, R related); private: typedef ModuleAbstractTracked Self; /** * Map of tracked items to customized objects. * * @GuardedBy this */ TrackingMap tracked; /** * Modification count. This field is initialized to zero and incremented by * modified. * * @GuardedBy this */ AtomicInt trackingCount; bool CustomizerAddingFinal(S item, const T& custom); }; US_END_NAMESPACE #include "usModuleAbstractTracked.tpp" #endif // USMODULEABSTRACTTRACKED_H diff --git a/Core/Code/CppMicroServices/src/service/usServiceTracker.tpp b/Core/Code/CppMicroServices/src/service/usServiceTracker.tpp index 17ab4757a5..608c628c61 100644 --- a/Core/Code/CppMicroServices/src/service/usServiceTracker.tpp +++ b/Core/Code/CppMicroServices/src/service/usServiceTracker.tpp @@ -1,448 +1,448 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include "usServiceTrackerPrivate.h" #include "usTrackedService_p.h" #include "usServiceException.h" #include "usModuleContext.h" #include #include US_BEGIN_NAMESPACE template ServiceTracker::~ServiceTracker() { Close(); delete d; } #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4355) #endif template ServiceTracker::ServiceTracker(ModuleContext* context, const ServiceReference& reference, _ServiceTrackerCustomizer* customizer) : d(new _ServiceTrackerPrivate(this, context, reference, customizer)) { } template ServiceTracker::ServiceTracker(ModuleContext* context, const std::string& clazz, _ServiceTrackerCustomizer* customizer) : d(new _ServiceTrackerPrivate(this, context, clazz, customizer)) { } template ServiceTracker::ServiceTracker(ModuleContext* context, const LDAPFilter& filter, _ServiceTrackerCustomizer* customizer) : d(new _ServiceTrackerPrivate(this, context, filter, customizer)) { } template ServiceTracker::ServiceTracker(ModuleContext *context, ServiceTrackerCustomizer *customizer) : d(new _ServiceTrackerPrivate(this, context, us_service_interface_iid(), customizer)) { const char* clazz = us_service_interface_iid(); if (clazz == 0) throw ServiceException("The service interface class has no US_DECLARE_SERVICE_INTERFACE macro"); } #ifdef _MSC_VER #pragma warning(pop) #endif template void ServiceTracker::Open() { _TrackedService* t; { typename _ServiceTrackerPrivate::Lock l(d); if (d->trackedService) { return; } - US_DEBUG(d->DEBUG) << "ServiceTracker::Open: " << d->filter; + US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker::Open: " << d->filter; t = new _TrackedService(this, d->customizer); { typename _TrackedService::Lock l(*t); try { d->context->AddServiceListener(t, &_TrackedService::ServiceChanged, d->listenerFilter); std::list references; if (!d->trackClass.empty()) { references = d->GetInitialReferences(d->trackClass, std::string()); } else { if (d->trackReference.GetModule() != 0) { references.push_back(d->trackReference); } else { /* user supplied filter */ references = d->GetInitialReferences(std::string(), (d->listenerFilter.empty()) ? d->filter.ToString() : d->listenerFilter); } } /* set tracked with the initial references */ t->SetInitial(references); } catch (const std::invalid_argument& e) { throw std::runtime_error(std::string("unexpected std::invalid_argument exception: ") + e.what()); } } d->trackedService = t; } /* Call tracked outside of synchronized region */ t->TrackInitial(); /* process the initial references */ } template void ServiceTracker::Close() { _TrackedService* outgoing; std::list references; { typename _ServiceTrackerPrivate::Lock l(d); outgoing = d->trackedService; if (outgoing == 0) { return; } - US_DEBUG(d->DEBUG) << "ServiceTracker::close:" << d->filter; + US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker::close:" << d->filter; outgoing->Close(); GetServiceReferences(references); d->trackedService = 0; try { d->context->RemoveServiceListener(outgoing, &_TrackedService::ServiceChanged); } catch (const std::logic_error& /*e*/) { /* In case the context was stopped. */ } } d->Modified(); /* clear the cache */ { typename _TrackedService::Lock l(outgoing); outgoing->NotifyAll(); /* wake up any waiters */ } for(std::list::const_iterator ref = references.begin(); ref != references.end(); ++ref) { outgoing->Untrack(*ref, ServiceEvent()); } - if (d->DEBUG) + if (d->DEBUG_OUTPUT) { typename _ServiceTrackerPrivate::Lock l(d); if ((d->cachedReference.GetModule() == 0) && (d->cachedService == 0)) { US_DEBUG(true) << "ServiceTracker::close[cached cleared]:" << d->filter; } } delete outgoing; d->trackedService = 0; } template T ServiceTracker::WaitForService(unsigned long timeoutMillis) { T object = GetService(); while (object == 0) { _TrackedService* t = d->Tracked(); if (t == 0) { /* if ServiceTracker is not open */ return 0; } { typename _TrackedService::Lock l(t); if (t->Size() == 0) { t->Wait(timeoutMillis); } } object = GetService(); } return object; } template void ServiceTracker::GetServiceReferences(std::list& refs) const { _TrackedService* t = d->Tracked(); if (t == 0) { /* if ServiceTracker is not open */ return; } { typename _TrackedService::Lock l(t); d->GetServiceReferences_unlocked(refs, t); } } template ServiceReference ServiceTracker::GetServiceReference() const { ServiceReference reference(0); { typename _ServiceTrackerPrivate::Lock l(d); reference = d->cachedReference; } if (reference.GetModule() != 0) { - US_DEBUG(d->DEBUG) << "ServiceTracker::getServiceReference[cached]:" + US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker::getServiceReference[cached]:" << d->filter; return reference; } - US_DEBUG(d->DEBUG) << "ServiceTracker::getServiceReference:" << d->filter; + US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker::getServiceReference:" << d->filter; std::list references; GetServiceReferences(references); std::size_t length = references.size(); if (length == 0) { /* if no service is being tracked */ throw ServiceException("No service is being tracked"); } std::list::const_iterator selectedRef; if (length > 1) { /* if more than one service, select highest ranking */ std::vector rankings(length); int count = 0; int maxRanking = std::numeric_limits::min(); std::list::const_iterator refIter = references.begin(); for (std::size_t i = 0; i < length; i++) { Any rankingAny = refIter->GetProperty(ServiceConstants::SERVICE_RANKING()); int ranking = 0; if (rankingAny.Type() == typeid(int)) { ranking = any_cast(rankingAny); } rankings[i] = ranking; if (ranking > maxRanking) { selectedRef = refIter; maxRanking = ranking; count = 1; } else { if (ranking == maxRanking) { count++; } } ++refIter; } if (count > 1) { /* if still more than one service, select lowest id */ long int minId = std::numeric_limits::max(); refIter = references.begin(); for (std::size_t i = 0; i < length; i++) { if (rankings[i] == maxRanking) { Any idAny = refIter->GetProperty(ServiceConstants::SERVICE_ID()); long int id = 0; if (idAny.Type() == typeid(long int)) { id = any_cast(idAny); } if (id < minId) { selectedRef = refIter; minId = id; } } ++refIter; } } } { typename _ServiceTrackerPrivate::Lock l(d); d->cachedReference = *selectedRef; return d->cachedReference; } } template T ServiceTracker::GetService(const ServiceReference& reference) const { _TrackedService* t = d->Tracked(); if (t == 0) { /* if ServiceTracker is not open */ return 0; } { typename _TrackedService::Lock l(t); return t->GetCustomizedObject(reference); } } template void ServiceTracker::GetServices(std::list& services) const { _TrackedService* t = d->Tracked(); if (t == 0) { /* if ServiceTracker is not open */ return; } { typename _TrackedService::Lock l(t); std::list references; d->GetServiceReferences_unlocked(references, t); for(std::list::const_iterator ref = references.begin(); ref != references.end(); ++ref) { services.push_back(t->GetCustomizedObject(*ref)); } } } template T ServiceTracker::GetService() const { T service = d->cachedService; if (service != 0) { - US_DEBUG(d->DEBUG) << "ServiceTracker::getService[cached]:" + US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker::getService[cached]:" << d->filter; return service; } - US_DEBUG(d->DEBUG) << "ServiceTracker::getService:" << d->filter; + US_DEBUG(d->DEBUG_OUTPUT) << "ServiceTracker::getService:" << d->filter; try { ServiceReference reference = GetServiceReference(); if (reference.GetModule() == 0) { return 0; } return d->cachedService = GetService(reference); } catch (const ServiceException&) { return 0; } } template void ServiceTracker::Remove(const ServiceReference& reference) { _TrackedService* t = d->Tracked(); if (t == 0) { /* if ServiceTracker is not open */ return; } t->Untrack(reference, ServiceEvent()); } template int ServiceTracker::Size() const { _TrackedService* t = d->Tracked(); if (t == 0) { /* if ServiceTracker is not open */ return 0; } { typename _TrackedService::Lock l(t); return static_cast(t->Size()); } } template int ServiceTracker::GetTrackingCount() const { _TrackedService* t = d->Tracked(); if (t == 0) { /* if ServiceTracker is not open */ return -1; } { typename _TrackedService::Lock l(t); return t->GetTrackingCount(); } } template void ServiceTracker::GetTracked(TrackingMap& map) const { _TrackedService* t = d->Tracked(); if (t == 0) { /* if ServiceTracker is not open */ return; } { typename _TrackedService::Lock l(t); t->CopyEntries(map); } } template bool ServiceTracker::IsEmpty() const { _TrackedService* t = d->Tracked(); if (t == 0) { /* if ServiceTracker is not open */ return true; } { typename _TrackedService::Lock l(t); return t->IsEmpty(); } } template T ServiceTracker::AddingService(const ServiceReference& reference) { return dynamic_cast(d->context->GetService(reference)); } template void ServiceTracker::ModifiedService(const ServiceReference& /*reference*/, T /*service*/) { /* do nothing */ } template void ServiceTracker::RemovedService(const ServiceReference& reference, T /*service*/) { d->context->UngetService(reference); } US_END_NAMESPACE diff --git a/Core/Code/CppMicroServices/src/service/usServiceTrackerPrivate.h b/Core/Code/CppMicroServices/src/service/usServiceTrackerPrivate.h index 2bb0dfcb0a..1229b68ca0 100644 --- a/Core/Code/CppMicroServices/src/service/usServiceTrackerPrivate.h +++ b/Core/Code/CppMicroServices/src/service/usServiceTrackerPrivate.h @@ -1,172 +1,172 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #ifndef USSERVICETRACKERPRIVATE_H #define USSERVICETRACKERPRIVATE_H #include "usServiceReference.h" #include "usLDAPFilter.h" US_BEGIN_NAMESPACE /** * \ingroup MicroServices */ template class ServiceTrackerPrivate : US_DEFAULT_THREADING > { public: ServiceTrackerPrivate(ServiceTracker* st, ModuleContext* context, const ServiceReference& reference, ServiceTrackerCustomizer* customizer); ServiceTrackerPrivate(ServiceTracker* st, ModuleContext* context, const std::string& clazz, ServiceTrackerCustomizer* customizer); ServiceTrackerPrivate(ServiceTracker* st, ModuleContext* context, const LDAPFilter& filter, ServiceTrackerCustomizer* customizer); ~ServiceTrackerPrivate(); /** * Returns the list of initial ServiceReferences that will be * tracked by this ServiceTracker. * * @param className The class name with which the service was registered, or * null for all services. * @param filterString The filter criteria or null for all * services. * @return The list of initial ServiceReferences. * @throws std::invalid_argument If the specified filterString has an * invalid syntax. */ std::list GetInitialReferences(const std::string& className, const std::string& filterString); void GetServiceReferences_unlocked(std::list& refs, TrackedService* t) const; /* set this to true to compile in debug messages */ - static const bool DEBUG; // = false; + static const bool DEBUG_OUTPUT; // = false; /** * The Module Context used by this ServiceTracker. */ ModuleContext* const context; /** * The filter used by this ServiceTracker which specifies the * search criteria for the services to track. */ LDAPFilter filter; /** * The ServiceTrackerCustomizer for this tracker. */ ServiceTrackerCustomizer* customizer; /** * Filter string for use when adding the ServiceListener. If this field is * set, then certain optimizations can be taken since we don't have a user * supplied filter. */ std::string listenerFilter; /** * Class name to be tracked. If this field is set, then we are tracking by * class name. */ std::string trackClass; /** * Reference to be tracked. If this field is set, then we are tracking a * single ServiceReference. */ ServiceReference trackReference; /** * Tracked services: ServiceReference -> customized Object and * ServiceListenerEntry object */ TrackedService* trackedService; /** * Accessor method for the current TrackedService object. This method is only * intended to be used by the unsynchronized methods which do not modify the * trackedService field. * * @return The current Tracked object. */ TrackedService* Tracked() const; /** * Called by the TrackedService object whenever the set of tracked services is * modified. Clears the cache. */ /* * This method must not be synchronized since it is called by TrackedService while * TrackedService is synchronized. We don't want synchronization interactions * between the listener thread and the user thread. */ void Modified(); /** * Cached ServiceReference for getServiceReference. */ mutable ServiceReference cachedReference; /** * Cached service object for GetService. * * This field is volatile since it is accessed by multiple threads. */ mutable T volatile cachedService; private: inline ServiceTracker* q_func() { return static_cast *>(q_ptr); } inline const ServiceTracker* q_func() const { return static_cast *>(q_ptr); } friend class ServiceTracker; ServiceTracker * const q_ptr; }; US_END_NAMESPACE #include "usServiceTrackerPrivate.tpp" #endif // USSERVICETRACKERPRIVATE_H diff --git a/Core/Code/CppMicroServices/src/service/usServiceTrackerPrivate.tpp b/Core/Code/CppMicroServices/src/service/usServiceTrackerPrivate.tpp index 5346e14b40..e48033f6a1 100644 --- a/Core/Code/CppMicroServices/src/service/usServiceTrackerPrivate.tpp +++ b/Core/Code/CppMicroServices/src/service/usServiceTrackerPrivate.tpp @@ -1,144 +1,144 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include "usTrackedService_p.h" #include "usModuleContext.h" #include "usLDAPFilter.h" #include US_BEGIN_NAMESPACE template -const bool ServiceTrackerPrivate::DEBUG = true; +const bool ServiceTrackerPrivate::DEBUG_OUTPUT = true; template ServiceTrackerPrivate::ServiceTrackerPrivate( ServiceTracker* st, ModuleContext* context, const ServiceReference& reference, ServiceTrackerCustomizer* customizer) : context(context), customizer(customizer), trackReference(reference), trackedService(0), cachedReference(0), cachedService(0), q_ptr(st) { this->customizer = customizer ? customizer : q_func(); std::stringstream ss; ss << "(" << ServiceConstants::SERVICE_ID() << "=" << any_cast(reference.GetProperty(ServiceConstants::SERVICE_ID())) << ")"; this->listenerFilter = ss.str(); try { this->filter = LDAPFilter(listenerFilter); } catch (const std::invalid_argument& e) { /* * we could only get this exception if the ServiceReference was * invalid */ std::invalid_argument ia(std::string("unexpected std::invalid_argument exception: ") + e.what()); throw ia; } } template ServiceTrackerPrivate::ServiceTrackerPrivate( ServiceTracker* st, ModuleContext* context, const std::string& clazz, ServiceTrackerCustomizer* customizer) : context(context), customizer(customizer), trackClass(clazz), trackReference(0), trackedService(0), cachedReference(0), cachedService(0), q_ptr(st) { this->customizer = customizer ? customizer : q_func(); this->listenerFilter = std::string("(") + US_PREPEND_NAMESPACE(ServiceConstants)::OBJECTCLASS() + "=" + clazz + ")"; try { this->filter = LDAPFilter(listenerFilter); } catch (const std::invalid_argument& e) { /* * we could only get this exception if the clazz argument was * malformed */ std::invalid_argument ia( std::string("unexpected std::invalid_argument exception: ") + e.what()); throw ia; } } template ServiceTrackerPrivate::ServiceTrackerPrivate( ServiceTracker* st, ModuleContext* context, const LDAPFilter& filter, ServiceTrackerCustomizer* customizer) : context(context), filter(filter), customizer(customizer), listenerFilter(filter.ToString()), trackReference(0), trackedService(0), cachedReference(0), cachedService(0), q_ptr(st) { this->customizer = customizer ? customizer : q_func(); if (context == 0) { throw std::invalid_argument("The module context cannot be null."); } } template ServiceTrackerPrivate::~ServiceTrackerPrivate() { } template std::list ServiceTrackerPrivate::GetInitialReferences( const std::string& className, const std::string& filterString) { return context->GetServiceReferences(className, filterString); } template void ServiceTrackerPrivate::GetServiceReferences_unlocked(std::list& refs, TrackedService* t) const { if (t->Size() == 0) { return; } t->GetTracked(refs); } template TrackedService* ServiceTrackerPrivate::Tracked() const { return trackedService; } template void ServiceTrackerPrivate::Modified() { cachedReference = 0; /* clear cached value */ cachedService = 0; /* clear cached value */ - US_DEBUG(DEBUG) << "ServiceTracker::Modified(): " << filter; + US_DEBUG(DEBUG_OUTPUT) << "ServiceTracker::Modified(): " << filter; } US_END_NAMESPACE diff --git a/Core/Code/CppMicroServices/src/service/usTrackedService.tpp b/Core/Code/CppMicroServices/src/service/usTrackedService.tpp index e1c1f709c0..8917c200fd 100644 --- a/Core/Code/CppMicroServices/src/service/usTrackedService.tpp +++ b/Core/Code/CppMicroServices/src/service/usTrackedService.tpp @@ -1,123 +1,123 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ US_BEGIN_NAMESPACE template TrackedService::TrackedService(ServiceTracker* serviceTracker, ServiceTrackerCustomizer* customizer) : serviceTracker(serviceTracker), customizer(customizer) { } template void TrackedService::ServiceChanged(const ServiceEvent event) { /* * Check if we had a delayed call (which could happen when we * close). */ if (this->closed) { return; } ServiceReference reference = event.GetServiceReference(); - US_DEBUG(serviceTracker->d->DEBUG) << "TrackedService::ServiceChanged[" + US_DEBUG(serviceTracker->d->DEBUG_OUTPUT) << "TrackedService::ServiceChanged[" << event.GetType() << "]: " << reference; switch (event.GetType()) { case ServiceEvent::REGISTERED : case ServiceEvent::MODIFIED : { if (!serviceTracker->d->listenerFilter.empty()) { // service listener added with filter this->Track(reference, event); /* * If the customizer throws an unchecked exception, it * is safe to let it propagate */ } else { // service listener added without filter if (serviceTracker->d->filter.Match(reference)) { this->Track(reference, event); /* * If the customizer throws an unchecked exception, * it is safe to let it propagate */ } else { this->Untrack(reference, event); /* * If the customizer throws an unchecked exception, * it is safe to let it propagate */ } } break; } case ServiceEvent::MODIFIED_ENDMATCH : case ServiceEvent::UNREGISTERING : this->Untrack(reference, event); /* * If the customizer throws an unchecked exception, it is * safe to let it propagate */ break; } } template void TrackedService::Modified() { Superclass::Modified(); /* increment the modification count */ serviceTracker->d->Modified(); } template T TrackedService::CustomizerAdding(ServiceReference item, const ServiceEvent& /*related*/) { return customizer->AddingService(item); } template void TrackedService::CustomizerModified(ServiceReference item, const ServiceEvent& /*related*/, T object) { customizer->ModifiedService(item, object); } template void TrackedService::CustomizerRemoved(ServiceReference item, const ServiceEvent& /*related*/, T object) { customizer->RemovedService(item, object); } US_END_NAMESPACE diff --git a/Core/Code/CppMicroServices/src/util/usUtils_p.h b/Core/Code/CppMicroServices/src/util/usUtils_p.h index d8183bd33e..32c88713e2 100644 --- a/Core/Code/CppMicroServices/src/util/usUtils_p.h +++ b/Core/Code/CppMicroServices/src/util/usUtils_p.h @@ -1,225 +1,225 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #ifndef USUTILS_H #define USUTILS_H #include #include #include #include //------------------------------------------------------------------- // Logging //------------------------------------------------------------------- US_BEGIN_NAMESPACE US_EXPORT void message_output(MsgType, const char* buf); struct LogMsg { LogMsg(int t, const char* file, int ln, const char* func) : type(static_cast(t)), enabled(true), buffer() { buffer << "In " << func << " at " << file << ":" << ln << " : "; } ~LogMsg() { if(enabled) message_output(type, buffer.str().c_str()); } template LogMsg& operator<<(T t) { if (enabled) buffer << t; return *this; } LogMsg& operator()(bool flag) { this->enabled = flag; return *this; } private: MsgType type; bool enabled; std::stringstream buffer; }; struct NoLogMsg { template NoLogMsg& operator<<(T) { return *this; } NoLogMsg& operator()(bool) { return *this; } }; US_END_NAMESPACE -#if !defined(US_NO_DEBUG_OUTPUT) +#if defined(US_ENABLE_DEBUG_OUTPUT) #define US_DEBUG US_PREPEND_NAMESPACE(LogMsg)(0, __FILE__, __LINE__, __FUNCTION__) #else #define US_DEBUG true ? US_PREPEND_NAMESPACE(NoLogMsg)() : US_PREPEND_NAMESPACE(NoLogMsg)() #endif #if !defined(US_NO_INFO_OUTPUT) #define US_INFO US_PREPEND_NAMESPACE(LogMsg)(1, __FILE__, __LINE__, __FUNCTION__) #else #define US_INFO true ? US_PREPEND_NAMESPACE(NoLogMsg)() : US_PREPEND_NAMESPACE(NoLogMsg)() #endif #if !defined(US_NO_WARNING_OUTPUT) #define US_WARN US_PREPEND_NAMESPACE(LogMsg)(2, __FILE__, __LINE__, __FUNCTION__) #else #define US_WARN true ? US_PREPEND_NAMESPACE(LogMsg)() : US_PREPEND_NAMESPACE(LogMsg)() #endif #define US_ERROR US_PREPEND_NAMESPACE(LogMsg)(3, __FILE__, __LINE__, __FUNCTION__) //------------------------------------------------------------------- // Module auto-loading //------------------------------------------------------------------- US_BEGIN_NAMESPACE struct ModuleInfo; void AutoLoadModules(const ModuleInfo& moduleInfo); US_END_NAMESPACE //------------------------------------------------------------------- // Error handling //------------------------------------------------------------------- US_BEGIN_NAMESPACE US_EXPORT std::string GetLastErrorStr(); US_END_NAMESPACE //------------------------------------------------------------------- // Functors //------------------------------------------------------------------- #include #include #if defined(US_USE_CXX11) || defined(__GNUC__) #ifdef US_USE_CXX11 #include #define US_MODULE_LISTENER_FUNCTOR std::function #define US_SERVICE_LISTENER_FUNCTOR std::function #else #include #define US_MODULE_LISTENER_FUNCTOR std::tr1::function #define US_SERVICE_LISTENER_FUNCTOR std::tr1::function #endif US_BEGIN_NAMESPACE template US_MODULE_LISTENER_FUNCTOR ModuleListenerMemberFunctor(X* x, void (X::*memFn)(const US_PREPEND_NAMESPACE(ModuleEvent))) { return std::bind1st(std::mem_fun(memFn), x); } US_END_NAMESPACE US_BEGIN_NAMESPACE struct ModuleListenerCompare : std::binary_function, std::pair, bool> { bool operator()(const std::pair& p1, const std::pair& p2) const { return p1.second == p2.second && p1.first.target() == p2.first.target(); } }; US_END_NAMESPACE US_BEGIN_NAMESPACE template US_SERVICE_LISTENER_FUNCTOR ServiceListenerMemberFunctor(X* x, void (X::*memFn)(const US_PREPEND_NAMESPACE(ServiceEvent))) { return std::bind1st(std::mem_fun(memFn), x); } US_END_NAMESPACE US_BEGIN_NAMESPACE struct ServiceListenerCompare : std::binary_function { bool operator()(const US_SERVICE_LISTENER_FUNCTOR& f1, const US_SERVICE_LISTENER_FUNCTOR& f2) const { return f1.target() == f2.target(); } }; US_END_NAMESPACE #else #include #define US_MODULE_LISTENER_FUNCTOR US_PREPEND_NAMESPACE(Functor) US_BEGIN_NAMESPACE template US_MODULE_LISTENER_FUNCTOR ModuleListenerMemberFunctor(X* x, MemFn memFn) { return Functor(x, memFn); } US_END_NAMESPACE US_BEGIN_NAMESPACE struct ModuleListenerCompare : std::binary_function, std::pair, bool> { bool operator()(const std::pair& p1, const std::pair& p2) const { return p1.second == p2.second && p1.first == p2.first; } }; US_END_NAMESPACE #define US_SERVICE_LISTENER_FUNCTOR US_PREPEND_NAMESPACE(Functor) US_BEGIN_NAMESPACE template US_SERVICE_LISTENER_FUNCTOR ServiceListenerMemberFunctor(X* x, MemFn memFn) { return Functor(x, memFn); } US_END_NAMESPACE US_BEGIN_NAMESPACE struct ServiceListenerCompare : std::binary_function { bool operator()(const US_SERVICE_LISTENER_FUNCTOR& f1, const US_SERVICE_LISTENER_FUNCTOR& f2) const { return f1 == f2; } }; US_END_NAMESPACE #endif #endif // USUTILS_H diff --git a/Core/Code/CppMicroServices/test/usDebugOutputTest.cpp b/Core/Code/CppMicroServices/test/usDebugOutputTest.cpp index 721ad6e351..c3aab61b92 100644 --- a/Core/Code/CppMicroServices/test/usDebugOutputTest.cpp +++ b/Core/Code/CppMicroServices/test/usDebugOutputTest.cpp @@ -1,100 +1,100 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include #include "usTestingMacros.h" US_USE_NAMESPACE static int lastMsgType = -1; static std::string lastMsg; void handleMessages(MsgType type, const char* msg) { lastMsgType = type; lastMsg.assign(msg); } void resetLastMsg() { lastMsgType = -1; lastMsg.clear(); } int usDebugOutputTest(int /*argc*/, char* /*argv*/[]) { US_TEST_BEGIN("DebugOutputTest"); // Use the default message handler { US_DEBUG << "Msg"; US_DEBUG(false) << "Msg"; US_INFO << "Msg"; US_INFO(false) << "Msg"; US_WARN << "Msg"; US_WARN(false) << "Msg"; } US_TEST_CONDITION(lastMsg.empty(), "Testing default message handler"); resetLastMsg(); installMsgHandler(handleMessages); { US_DEBUG << "Msg"; } -#ifdef NDEBUG +#if !defined(US_ENABLE_DEBUG_OUTPUT) US_TEST_CONDITION(lastMsgType == -1 && lastMsg.empty(), "Testing suppressed debug message") #else US_TEST_CONDITION(lastMsgType == 0 && lastMsg.find("Msg") != std::string::npos, "Testing debug message") #endif resetLastMsg(); { US_DEBUG(false) << "No msg"; } US_TEST_CONDITION(lastMsgType == -1 && lastMsg.empty(), "Testing disabled debug message") resetLastMsg(); { US_INFO << "Info msg"; } US_TEST_CONDITION(lastMsgType == 1 && lastMsg.find("Info msg") != std::string::npos, "Testing informational message") resetLastMsg(); { US_WARN << "Warn msg"; } US_TEST_CONDITION(lastMsgType == 2 && lastMsg.find("Warn msg") != std::string::npos, "Testing warning message") resetLastMsg(); // We cannot test US_ERROR since it will call abort(). installMsgHandler(0); { US_INFO << "Info msg"; } US_TEST_CONDITION(lastMsgType == -1 && lastMsg.empty(), "Testing message handler reset") US_TEST_END() } diff --git a/Core/Code/CppMicroServices/test/usStaticModuleResourceTest.cpp b/Core/Code/CppMicroServices/test/usStaticModuleResourceTest.cpp index dc73a7fe72..2405f4572a 100644 --- a/Core/Code/CppMicroServices/test/usStaticModuleResourceTest.cpp +++ b/Core/Code/CppMicroServices/test/usStaticModuleResourceTest.cpp @@ -1,151 +1,151 @@ /*============================================================================= Library: CppMicroServices Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =============================================================================*/ #include #include #include #include #include #include #include #include "usTestUtilSharedLibrary.h" #include "usTestingMacros.h" #include #include US_USE_NAMESPACE namespace { std::string GetResourceContent(const ModuleResource& resource) { std::string line; ModuleResourceStream rs(resource); std::getline(rs, line); return line; } struct ResourceComparator { bool operator()(const ModuleResource& mr1, const ModuleResource& mr2) const { return mr1 < mr2; } }; void testResourceOperators(Module* module) { std::vector resources = module->FindResources("", "res.txt", false); US_TEST_CONDITION_REQUIRED(resources.size() == 2, "Check resource count") US_TEST_CONDITION(resources[0] != resources[1], "Check non-equality for equally named resources") } void testResourcesWithStaticImport(Module* module) { ModuleResource resource = module->GetResource("res.txt"); US_TEST_CONDITION_REQUIRED(resource.IsValid(), "Check valid res.txt resource") std::string line = GetResourceContent(resource); US_TEST_CONDITION(line == "dynamic resource", "Check dynamic resource content") resource = module->GetResource("dynamic.txt"); US_TEST_CONDITION_REQUIRED(resource.IsValid(), "Check valid dynamic.txt resource") line = GetResourceContent(resource); US_TEST_CONDITION(line == "dynamic", "Check dynamic resource content") resource = module->GetResource("static.txt"); US_TEST_CONDITION_REQUIRED(resource.IsValid(), "Check valid static.txt resource") line = GetResourceContent(resource); US_TEST_CONDITION(line == "static", "Check dynamic resource content") std::vector resources = module->FindResources("", "*.txt", false); std::stable_sort(resources.begin(), resources.end(), ResourceComparator()); #ifdef US_BUILD_SHARED_LIBS US_TEST_CONDITION(resources.size() == 4, "Check imported resource count") line = GetResourceContent(resources[0]); US_TEST_CONDITION(line == "dynamic", "Check dynamic.txt resource content") line = GetResourceContent(resources[1]); US_TEST_CONDITION(line == "dynamic resource", "Check res.txt (from importing module) resource content") line = GetResourceContent(resources[2]); US_TEST_CONDITION(line == "static resource", "Check res.txt (from imported module) resource content") line = GetResourceContent(resources[3]); US_TEST_CONDITION(line == "static", "Check static.txt (from importing module) resource content") #else US_TEST_CONDITION(resources.size() == 6, "Check imported resource count") line = GetResourceContent(resources[0]); US_TEST_CONDITION(line == "dynamic", "Check dynamic.txt resource content") // skip foo.txt line = GetResourceContent(resources[2]); US_TEST_CONDITION(line == "dynamic resource", "Check res.txt (from importing module) resource content") line = GetResourceContent(resources[3]); US_TEST_CONDITION(line == "static resource", "Check res.txt (from imported module) resource content") // skip special_chars.dummy.txt line = GetResourceContent(resources[5]); US_TEST_CONDITION(line == "static", "Check static.txt (from importing module) resource content") #endif } } // end unnamed namespace int usStaticModuleResourceTest(int /*argc*/, char* /*argv*/[]) { US_TEST_BEGIN("StaticModuleResourceTest"); - ModuleContext* mc = GetModuleContext(); - assert(mc); + assert(GetModuleContext()); + #ifdef US_BUILD_SHARED_LIBS SharedLibraryHandle libB("TestModuleB"); try { libB.Load(); } catch (const std::exception& e) { US_TEST_FAILED_MSG(<< "Load module exception: " << e.what()) } Module* module = ModuleRegistry::GetModule("TestModuleB Module"); US_TEST_CONDITION_REQUIRED(module != NULL, "Test for existing module TestModuleB") US_TEST_CONDITION(module->GetName() == "TestModuleB Module", "Test module name") #else - Module* module = mc->GetModule(); + Module* module = GetModuleContext()->GetModule(); #endif testResourceOperators(module); testResourcesWithStaticImport(module); #ifdef US_BUILD_SHARED_LIBS ModuleResource resource = module->GetResource("static.txt"); US_TEST_CONDITION_REQUIRED(resource.IsValid(), "Check valid static.txt resource") libB.Unload(); US_TEST_CONDITION_REQUIRED(resource.IsValid() == false, "Check invalid static.txt resource") #endif US_TEST_END() } diff --git a/Core/Code/CppMicroServices/usConfig.h.in b/Core/Code/CppMicroServices/usConfig.h.in index 59c59a4753..97ab1a3d43 100644 --- a/Core/Code/CppMicroServices/usConfig.h.in +++ b/Core/Code/CppMicroServices/usConfig.h.in @@ -1,253 +1,251 @@ /* USCONFIG.h this file is generated. Do not change! */ #ifndef USCONFIG_H #define USCONFIG_H #cmakedefine US_BUILD_SHARED_LIBS #cmakedefine CppMicroServices_EXPORTS #cmakedefine US_ENABLE_AUTOLOADING_SUPPORT #cmakedefine US_ENABLE_THREADING_SUPPORT #cmakedefine US_ENABLE_SERVICE_FACTORY_SUPPORT #cmakedefine US_USE_CXX11 ///------------------------------------------------------------------- // Version information //------------------------------------------------------------------- #define CppMicroServices_VERSION_MAJOR @CppMicroServices_VERSION_MAJOR@ #define CppMicroServices_VERSION_MINOR @CppMicroServices_VERSION_MINOR@ #define CppMicroServices_VERSION_PATH @CppMicroServices_VERSION_PATCH@ #define CppMicroServices_VERSION @CppMicroServices_VERSION@ #define CppMicroServices_VERSION_STR "@CppMicroServices_VERSION@" ///------------------------------------------------------------------- // Macros used by the unit tests //------------------------------------------------------------------- #define CppMicroServices_SOURCE_DIR "@CppMicroServices_SOURCE_DIR@" ///------------------------------------------------------------------- // Macros for import/export declarations //------------------------------------------------------------------- #if defined(WIN32) #define US_ABI_EXPORT __declspec(dllexport) #define US_ABI_IMPORT __declspec(dllimport) #define US_ABI_LOCAL #else #if __GNUC__ >= 4 #define US_ABI_EXPORT __attribute__ ((visibility ("default"))) #define US_ABI_IMPORT __attribute__ ((visibility ("default"))) #define US_ABI_LOCAL __attribute__ ((visibility ("hidden"))) #else #define US_ABI_EXPORT #define US_ABI_IMPORT #define US_ABI_LOCAL #endif #endif #ifdef US_BUILD_SHARED_LIBS // We are building a shared lib #ifdef CppMicroServices_EXPORTS #define US_EXPORT US_ABI_EXPORT #else #define US_EXPORT US_ABI_IMPORT #endif #else // We are building a static lib #if __GNUC__ >= 4 // Don't hide RTTI symbols of definitions in the C++ Micro Services // headers that are included in DSOs with hidden visibility #define US_EXPORT US_ABI_EXPORT #else #define US_EXPORT #endif #endif //------------------------------------------------------------------- // Namespace customization //------------------------------------------------------------------- #define US_NAMESPACE @US_NAMESPACE@ #ifndef US_NAMESPACE /* user namespace */ # define US_PREPEND_NAMESPACE(name) ::name # define US_USE_NAMESPACE # define US_BEGIN_NAMESPACE # define US_END_NAMESPACE # define US_FORWARD_DECLARE_CLASS(name) class name; # define US_FORWARD_DECLARE_STRUCT(name) struct name; #else /* user namespace */ # define US_PREPEND_NAMESPACE(name) ::US_NAMESPACE::name # define US_USE_NAMESPACE using namespace ::US_NAMESPACE; # define US_BEGIN_NAMESPACE namespace US_NAMESPACE { # define US_END_NAMESPACE } # define US_FORWARD_DECLARE_CLASS(name) \ US_BEGIN_NAMESPACE class name; US_END_NAMESPACE # define US_FORWARD_DECLARE_STRUCT(name) \ US_BEGIN_NAMESPACE struct name; US_END_NAMESPACE namespace US_NAMESPACE {} #endif /* user namespace */ #define US_BASECLASS_NAME @US_BASECLASS_NAME@ #define US_BASECLASS_HEADER <@US_BASECLASS_HEADER@> // base class forward declaration @US_BASECLASS_FORWARD_DECLARATION@ //------------------------------------------------------------------- // Platform defines //------------------------------------------------------------------- #if defined(__APPLE__) #define US_PLATFORM_APPLE #endif #if defined(__linux__) #define US_PLATFORM_LINUX #endif #if defined(_WIN32) || defined(_WIN64) #define US_PLATFORM_WINDOWS #else #define US_PLATFORM_POSIX #endif //------------------------------------------------------------------- // Macros for suppressing warnings //------------------------------------------------------------------- #ifdef _MSC_VER #define US_MSVC_PUSH_DISABLE_WARNING(wn) \ __pragma(warning(push)) \ __pragma(warning(disable:wn)) #define US_MSVC_POP_WARNING \ __pragma(warning(pop)) #define US_MSVC_DISABLE_WARNING(wn) \ __pragma(warning(disable:wn)) #else #define US_MSVC_PUSH_DISABLE_WARNING(wn) #define US_MSVC_POP_WARNING #define US_MSVC_DISABLE_WARNING(wn) #endif // Do not warn about the usage of deprecated unsafe functions US_MSVC_DISABLE_WARNING(4996) //------------------------------------------------------------------- // Debuging & Logging //------------------------------------------------------------------- -#if defined(NDEBUG) && !defined(US_NO_DEBUG_OUTPUT) - #define US_NO_DEBUG_OUTPUT -#endif +#cmakedefine US_ENABLE_DEBUG_OUTPUT US_BEGIN_NAMESPACE enum MsgType { DebugMsg = 0, InfoMsg = 1, WarningMsg = 2, ErrorMsg = 3 }; typedef void (*MsgHandler)(MsgType, const char *); US_EXPORT MsgHandler installMsgHandler(MsgHandler); US_END_NAMESPACE //------------------------------------------------------------------- // Hash Container //------------------------------------------------------------------- #ifdef US_USE_CXX11 #include #include #define US_HASH_FUNCTION_BEGIN(type) \ template<> \ struct hash : std::unary_function { \ std::size_t operator()(const type& arg) const { #define US_HASH_FUNCTION_END } }; #define US_HASH_FUNCTION(type, arg) hash()(arg) #if defined(US_PLATFORM_WINDOWS) && (_MSC_VER < 1700) #define US_HASH_FUNCTION_FRIEND(type) friend class ::std::hash #else #define US_HASH_FUNCTION_FRIEND(type) friend struct ::std::hash #endif #define US_UNORDERED_MAP_TYPE ::std::unordered_map #define US_UNORDERED_SET_TYPE ::std::unordered_set #define US_HASH_FUNCTION_NAMESPACE ::std #define US_HASH_FUNCTION_NAMESPACE_BEGIN namespace std { #define US_HASH_FUNCTION_NAMESPACE_END } #elif defined(__GNUC__) #include #include #define US_HASH_FUNCTION_BEGIN(type) \ template<> \ struct hash : std::unary_function { \ std::size_t operator()(const type& arg) const { #define US_HASH_FUNCTION_END } }; #define US_HASH_FUNCTION(type, arg) hash()(arg) #define US_HASH_FUNCTION_FRIEND(type) friend struct ::std::tr1::hash #define US_UNORDERED_MAP_TYPE ::std::tr1::unordered_map #define US_UNORDERED_SET_TYPE ::std::tr1::unordered_set #define US_HASH_FUNCTION_NAMESPACE ::std::tr1 #define US_HASH_FUNCTION_NAMESPACE_BEGIN namespace std { namespace tr1 { #define US_HASH_FUNCTION_NAMESPACE_END }} #elif _MSC_VER <= 1500 // Visual Studio 2008 and lower #include #include #define US_HASH_FUNCTION_BEGIN(type) \ template<> \ inline std::size_t hash_value(const type& arg) { #define US_HASH_FUNCTION_END } #define US_HASH_FUNCTION(type, arg) hash_value(arg) #define US_HASH_FUNCTION_FRIEND(type) friend std::size_t stdext::hash_value(const type&) #define US_UNORDERED_MAP_TYPE ::stdext::hash_map #define US_UNORDERED_SET_TYPE ::stdext::hash_set #define US_HASH_FUNCTION_NAMESPACE ::stdext #define US_HASH_FUNCTION_NAMESPACE_BEGIN namespace stdext { #define US_HASH_FUNCTION_NAMESPACE_END } #endif //------------------------------------------------------------------- // Threading Configuration //------------------------------------------------------------------- #ifdef US_ENABLE_THREADING_SUPPORT #define US_DEFAULT_THREADING US_PREPEND_NAMESPACE(MultiThreaded) #else #define US_DEFAULT_THREADING US_PREPEND_NAMESPACE(SingleThreaded) #endif //------------------------------------------------------------------- // Header Availability //------------------------------------------------------------------- #cmakedefine HAVE_STDINT #endif // USCONFIG_H diff --git a/Core/Code/Interactions/mitkBindDispatcherInteractor.cpp b/Core/Code/Interactions/mitkBindDispatcherInteractor.cpp index 8bf243c4d0..cc8c0f0189 100644 --- a/Core/Code/Interactions/mitkBindDispatcherInteractor.cpp +++ b/Core/Code/Interactions/mitkBindDispatcherInteractor.cpp @@ -1,117 +1,111 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBindDispatcherInteractor.h" #include "mitkMessage.h" #include // us #include "mitkGetModuleContext.h" #include "mitkModule.h" #include "mitkModuleRegistry.h" -#include "mitkInformer.h" +//#include "mitkInformer.h" mitk::BindDispatcherInteractor::BindDispatcherInteractor() : m_DataStorage(NULL),m_InformerService(NULL) { ModuleContext* context = ModuleRegistry::GetModule(1)->GetModuleContext(); if (context == NULL) { MITK_ERROR<< "BindDispatcherInteractor() - Context could not be obtained."; return; } - ServiceReference serviceRef = context->GetServiceReference(); - if (!serviceRef) - { // the service should only be registered once - m_InformerService = new InformerService(); - context->RegisterService(m_InformerService); - } m_Dispatcher = Dispatcher::New(); } void mitk::BindDispatcherInteractor::SetDataStorage(mitk::DataStorage::Pointer dataStorage) { // Set/Change Datastorage. This registers BDI to listen for events of DataStorage, to be informed when // a DataNode with a Interactor is added/modified/removed. // clean up events from previous datastorage UnRegisterDataStorageEvents(); m_DataStorage = dataStorage; RegisterDataStorageEvents(); } mitk::BindDispatcherInteractor::~BindDispatcherInteractor() { if (m_DataStorage.IsNotNull()) { UnRegisterDataStorageEvents(); } } void mitk::BindDispatcherInteractor::RegisterInteractor(const mitk::DataNode* dataNode) { if (m_Dispatcher.IsNotNull()) { m_Dispatcher->AddDataInteractor(dataNode); } } void mitk::BindDispatcherInteractor::RegisterDataStorageEvents() { if (m_DataStorage.IsNotNull()) { m_DataStorage->AddNodeEvent.AddListener( MessageDelegate1(this, &BindDispatcherInteractor::RegisterInteractor)); m_DataStorage->RemoveNodeEvent.AddListener( MessageDelegate1(this, &BindDispatcherInteractor::UnRegisterInteractor)); m_DataStorage->ChangedNodeEvent.AddListener( MessageDelegate1(this, &BindDispatcherInteractor::RegisterInteractor)); } } void mitk::BindDispatcherInteractor::UnRegisterInteractor(const DataNode* dataNode) { if (m_Dispatcher.IsNotNull()) { m_Dispatcher->RemoveDataInteractor(dataNode); } } -mitk::Dispatcher::Pointer mitk::BindDispatcherInteractor::GetDispatcher() +const mitk::Dispatcher::Pointer mitk::BindDispatcherInteractor::GetDispatcher() { return m_Dispatcher; } void mitk::BindDispatcherInteractor::SetDispatcher(Dispatcher::Pointer dispatcher) { m_Dispatcher = dispatcher; } void mitk::BindDispatcherInteractor::UnRegisterDataStorageEvents() { if (m_DataStorage.IsNotNull()) { m_DataStorage->AddNodeEvent.RemoveListener( MessageDelegate1(this, &BindDispatcherInteractor::RegisterInteractor)); m_DataStorage->RemoveNodeEvent.RemoveListener( MessageDelegate1(this, &BindDispatcherInteractor::UnRegisterInteractor)); m_DataStorage->ChangedNodeEvent.RemoveListener( MessageDelegate1(this, &BindDispatcherInteractor::RegisterInteractor)); } } diff --git a/Core/Code/Interactions/mitkBindDispatcherInteractor.h b/Core/Code/Interactions/mitkBindDispatcherInteractor.h index 773ad37736..87e1571fc2 100644 --- a/Core/Code/Interactions/mitkBindDispatcherInteractor.h +++ b/Core/Code/Interactions/mitkBindDispatcherInteractor.h @@ -1,87 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkBindDispatcherInteractor_h #define mitkBindDispatcherInteractor_h -#include "itkObject.h" -#include "itkObjectFactory.h" #include "mitkCommon.h" #include #include "mitkDataStorage.h" #include "mitkDataNode.h" #include "mitkDispatcher.h" namespace mitk { class InformerService; /** * \class BindDispatcherInteractor * \brief This Class is used to connect a DataStorage with the Dispatcher. + * * This is done by registering for DataStorage Events and sending the Events to the registered Dispatcher. * When a DataInteractor is registered with a DataNode the Dispatcher will be notified. - * Also this class registers the MicroService at which EventObservers can register to receive events. + * Also this class registers the MicroService at which InteractionEventObservers can register to receive events. * * \ingroup Interaction */ - class MITK_CORE_EXPORT BindDispatcherInteractor: public itk::Object + class MITK_CORE_EXPORT BindDispatcherInteractor { public: - mitkClassMacro(BindDispatcherInteractor, itk::Object); - itkNewMacro(Self); + BindDispatcherInteractor(); + ~BindDispatcherInteractor(); /** * Sets the DataStorage to which Events the class subscribes. */ void SetDataStorage(DataStorage::Pointer dataStorage); /** * Sets Dispatcher which will be notified. By default each RenderWindow gets its own Dispatcher, * this function can be used to override this behavior. */ void SetDispatcher(Dispatcher::Pointer dispatcher); /** * Return currently active Dispatcher. */ - Dispatcher::Pointer GetDispatcher(); + const Dispatcher::Pointer GetDispatcher(); - protected: - - BindDispatcherInteractor(); - virtual ~BindDispatcherInteractor(); private: /** @brief Registers for events from DataStorage. * * This way whenever a DataNode is added the Dispatcher is notified about this change, and checks whether a DataInteractor * is set for this DataNode */ void RegisterInteractor(const DataNode* dataNode); void UnRegisterInteractor(const DataNode* dataNode); void RegisterDataStorageEvents(); void UnRegisterDataStorageEvents(); Dispatcher::Pointer m_Dispatcher; DataStorage::Pointer m_DataStorage; InformerService* m_InformerService; // holds reference to MicroService that notifies listeners }; } #endif /* mitkBindDispatcherInteractor_h */ diff --git a/Core/Code/Interactions/mitkDataInteractor.cpp b/Core/Code/Interactions/mitkDataInteractor.cpp index 93963e30b6..c99f9e01d8 100644 --- a/Core/Code/Interactions/mitkDataInteractor.cpp +++ b/Core/Code/Interactions/mitkDataInteractor.cpp @@ -1,121 +1,93 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDataInteractor.h" #include "mitkInteractor.h" #include "mitkPointSet.h" #include "mitkDataNode.h" #include "mitkStateMachineState.h" mitk::DataInteractor::DataInteractor() { - m_SelectionAccuracy = 3.5; } -mitk::DataNode::Pointer mitk::DataInteractor::GetDataNode() +mitk::DataInteractor::NodeType mitk::DataInteractor::GetDataNode() const { return m_DataNode; } void mitk::DataInteractor::SetDataNode(DataNode::Pointer dataNode) { if (dataNode == m_DataNode) return; if (m_DataNode.IsNotNull()) { // if DataInteractors' DataNode is set to null, the "old" DataNode has to be notified (else the Dispatcher won't be notified either) m_DataNode->SetDataInteractor(NULL); } m_DataNode = dataNode; if (m_DataNode.IsNotNull()) { m_DataNode->SetDataInteractor(this); } // notify implementations ... DataNodeChanged(); } -int mitk::DataInteractor::GetLayer() +int mitk::DataInteractor::GetLayer() const { int layer = -1; if (m_DataNode.IsNotNull()) { m_DataNode->GetIntProperty("layer", layer); } return layer; } mitk::DataInteractor::~DataInteractor() { if (m_DataNode.IsNotNull()) { m_DataNode->SetInteractor(NULL); } } -void mitk::DataInteractor::SetAccuracy(float accuracy) -{ - m_SelectionAccuracy = accuracy; -} - void mitk::DataInteractor::ConnectActionsAndFunctions() { MITK_WARN<< "ConnectActionsAndFunctions in DataInteractor not implemented.\n DataInteractor will not be able to process any events."; } mitk::ProcessEventMode mitk::DataInteractor::GetMode() { if (GetCurrentState()->GetMode() == "PREFER_INPUT") { return PREFERINPUT; } if (GetCurrentState()->GetMode() == "GRAB_INPUT") { return GRABINPUT; } return REGULAR; } -int mitk::DataInteractor::GetPointIndexByPosition(Point3D position, int time) -{ - - // iterate over point set and check if it contains a point close enough to the pointer to be selected - PointSet* points = dynamic_cast(GetDataNode()->GetData()); - int index = -1; - if (points == NULL) - { - return index; - } - PointSet::PointsContainer* pointsContainer = points->GetPointSet(time)->GetPoints(); - float minDistance = m_SelectionAccuracy; - for (PointSet::PointsIterator it = pointsContainer->Begin(); it != pointsContainer->End(); it++) - { - float distance = sqrt(position.SquaredEuclideanDistanceTo(points->GetPoint(it->Index(), time))); // TODO: support time! - if (distance < minDistance) // if several points fall within the margin, choose the one with minimal distance to position - { // TODO: does this make sense, which unit is it? - index = it->Index(); - } - } - return index; -} void mitk::DataInteractor::DataNodeChanged() { } diff --git a/Core/Code/Interactions/mitkDataInteractor.h b/Core/Code/Interactions/mitkDataInteractor.h index ec9982b3d3..94cd3b5d58 100644 --- a/Core/Code/Interactions/mitkDataInteractor.h +++ b/Core/Code/Interactions/mitkDataInteractor.h @@ -1,126 +1,100 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKEVENTINTERACTOR_H_ #define MITKEVENTINTERACTOR_H_ -#include "itkObject.h" #include "itkSmartPointer.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include #include "mitkEventStateMachine.h" #include namespace mitk { /** * \class DataInteractor * * \brief Base class from with interactors that handle DataNodes are to be derived. * * Base class from with interactors that handle DataNodes are to be derived. * Provides an interface that is relevant for the interactor to work together with the dispatcher. * To implement a new interactor overwrite the ConnectActionsAndFunctions to connect the actions. */ // Public 'cause it's also used by the mitk::Dispatcher enum ProcessEventMode { REGULAR = 0, GRABINPUT = 1, PREFERINPUT = 2, CONNECTEDMOUSEACTION = 3 // only used by mitk::Dispatcher }; class DataNode; class MITK_CORE_EXPORT DataInteractor: public EventStateMachine { public: typedef itk::SmartPointer NodeType; - mitkClassMacro(DataInteractor, EventStateMachine); - itkNewMacro(Self); + mitkClassMacro(DataInteractor, EventStateMachine) + itkNewMacro(Self) /** * Set/Change the DataNode of the DataInteractor */ void SetDataNode(NodeType); - /** - * Sets the maximum distance that is accepted when looking for a point at a certain position using the GetPointIndexByPosition function. - */ - void SetAccuracy(float accuracy); - /** * @brief Returns the mode the DataInteractor currently is in. See in mitkDispatcher the description of m_ProcessingMode for further details. */ ProcessEventMode GetMode(); - NodeType GetDataNode(); - int GetLayer(); + NodeType GetDataNode() const; + int GetLayer() const; protected: DataInteractor(); virtual ~DataInteractor(); /** * @brief Overwrite this function to connect actions from StateMachine description with functions. * * Following example shows how to connect the 'addpoint' action from the StateMachine XML description using the CONNECT_FUNCTION macro * with the AddPoint() function in the TestInteractor. * @code * void mitk::TestInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addpoint", AddPoint); } * @endcode */ virtual void ConnectActionsAndFunctions(); - /** - * @ brief Return index in PointSet of the point that is within given accuracy to the provided position. - * - * Assumes that the DataNode contains a PointSet, if so it iterates over all points - * in the DataNode to check if it contains a point near the pointer position. - * If a point is found its index-position is returned, else -1 is returned. - */ - virtual int GetPointIndexByPosition(Point3D position, int time = 0); - /** \brief Is called when a DataNode is initially set or changed * To be implemented by sub-classes for initialization code which require a DataNode. * \note New DataInteractors usually are expected to have the focus, but this only works if they have the highest Layer, * since empty DataNodes have a layer of -1, the DataNode must be filled here in order to get a layer assigned. * \note Is also called when the DataNode is set to NULL. - * */ virtual void DataNodeChanged(); - /** \brief Is called when a DataNode is initially set or changed - * - * To be implemented by sub-classes for initialization code which require a DataNode. - * \note New DataInteractors usually are expected to have the focus, but this only works if they have the highest Layer, - * since empty DataNodes have a layer of -1, the DataNode must be filled here in order to get a layer assigned. - * \note Is also called when the DataNode is set to NULL. - * - */ - private: NodeType m_DataNode; - float m_SelectionAccuracy; }; } /* namespace mitk */ #endif /* MITKEVENTINTERACTOR_H_ */ diff --git a/Core/Code/Interactions/mitkDispatcher.cpp b/Core/Code/Interactions/mitkDispatcher.cpp index 26f82ac5f5..4207d4dbca 100644 --- a/Core/Code/Interactions/mitkDispatcher.cpp +++ b/Core/Code/Interactions/mitkDispatcher.cpp @@ -1,217 +1,233 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDispatcher.h" #include "mitkInteractionEvent.h" #include "mitkInternalEvent.h" // MicroServices #include "mitkGetModuleContext.h" #include "mitkModule.h" #include "mitkModuleRegistry.h" -#include "mitkInformer.h" +#include "mitkInteractionEventObserver.h" -mitk::Dispatcher::Dispatcher() + +mitk::Dispatcher::Dispatcher() : + m_ProcessingMode(REGULAR) { - m_ProcessingMode = REGULAR; - // get service to inform EventObserver - mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); - mitk::ServiceReference serviceRef = context->GetServiceReference(); - m_InformerService = dynamic_cast(context->GetService(serviceRef)); + m_EventObserverTracker = new mitk::ServiceTracker(GetModuleContext()); + m_EventObserverTracker->Open(); } void mitk::Dispatcher::AddDataInteractor(const DataNode* dataNode) { RemoveDataInteractor(dataNode); RemoveOrphanedInteractors(); DataInteractor::Pointer dataInteractor = dataNode->GetDataInteractor(); if (dataInteractor.IsNotNull()) { m_Interactors.push_back(dataInteractor); } } /* * Note: One DataInteractor can only have one DataNode and vice versa, * BUT the m_Interactors list may contain another DataInteractor that is still connected to this DataNode, * in this case we have to remove >1 DataInteractor. (Some special case of switching DataNodes between DataInteractors and registering a * DataNode to a DataStorage after assigning it to an DataInteractor) */ void mitk::Dispatcher::RemoveDataInteractor(const DataNode* dataNode) { for (ListInteractorType::iterator it = m_Interactors.begin(); it != m_Interactors.end();) { if ((*it)->GetDataNode() == dataNode) { it = m_Interactors.erase(it); } else { ++it; } } } size_t mitk::Dispatcher::GetNumberOfInteractors() { return m_Interactors.size(); } mitk::Dispatcher::~Dispatcher() { + m_EventObserverTracker->Close(); + delete m_EventObserverTracker; } bool mitk::Dispatcher::ProcessEvent(InteractionEvent* event) { InteractionEvent::Pointer p = event; //MITK_INFO << event->GetEventClass(); bool eventIsHandled = false; /* Filter out and handle Internal Events separately */ InternalEvent* internalEvent = dynamic_cast(event); if (internalEvent != NULL) { eventIsHandled = HandleInternalEvent(internalEvent); // InternalEvents that are handled are not sent to the listeners if (eventIsHandled) { return true; } } switch (m_ProcessingMode) { case CONNECTEDMOUSEACTION: // finished connected mouse action if (p->GetEventClass() == "MouseReleaseEvent") { m_ProcessingMode = REGULAR; eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()); } // give event to selected interactor if (eventIsHandled == false) { eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()); } break; case GRABINPUT: eventIsHandled = m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()); SetEventProcessingMode(m_SelectedInteractor); break; case PREFERINPUT: if (m_SelectedInteractor->HandleEvent(event, m_SelectedInteractor->GetDataNode()) == true) { SetEventProcessingMode(m_SelectedInteractor); eventIsHandled = true; } break; case REGULAR: break; } // Standard behavior. Is executed in STANDARD mode and PREFERINPUT mode, if preferred interactor rejects event. if (m_ProcessingMode == REGULAR || (m_ProcessingMode == PREFERINPUT && eventIsHandled == false)) { m_Interactors.sort(cmp()); // sorts interactors by layer (descending); for (std::list::iterator it = m_Interactors.begin(); it != m_Interactors.end(); ++it) { // explicit copy of pointer because HandleEvent function causes the m_Interactors list to be updated, // which in turn invalidates the iterator. DataInteractor::Pointer dataInteractor = *it; if (dataInteractor->HandleEvent(event, dataInteractor->GetDataNode())) { // if an event is handled several properties are checked, in order to determine the processing mode of the dispatcher SetEventProcessingMode(dataInteractor); if (p->GetEventClass() == "MousePressEvent" && m_ProcessingMode == REGULAR) { m_SelectedInteractor = dataInteractor; m_ProcessingMode = CONNECTEDMOUSEACTION; } eventIsHandled = true; break; } } } - /* Notify EventObserver */ - m_InformerService->NotifyObservers(event, eventIsHandled); + /* Notify InteractionEventObserver */ + std::list listEventObserver; + m_EventObserverTracker->GetServiceReferences(listEventObserver); + for (std::list::iterator it = listEventObserver.begin(); it != listEventObserver.end(); ++it) + { + + Any patternName = it->GetProperty("org.mitk.statemachinepattern"); + + //if (!patternName.Empty() || patternName.ToString() == "") + //{ + InteractionEventObserver* interactionEventObserver = m_EventObserverTracker->GetService(*it); + if (interactionEventObserver != NULL) + { + interactionEventObserver->Notify(event, eventIsHandled); + } + //} + } // Process event queue if (!m_QueuedEvents.empty()) { InteractionEvent::Pointer e = m_QueuedEvents.front(); m_QueuedEvents.pop_front(); ProcessEvent(e); } return eventIsHandled; } /* * Checks if DataNodes associated with DataInteractors point back to them. * If not remove the DataInteractors. (This can happen when s.o. tries to set DataNodes to multiple DataInteractors) */ void mitk::Dispatcher::RemoveOrphanedInteractors() { for (ListInteractorType::iterator it = m_Interactors.begin(); it != m_Interactors.end();) { DataNode::Pointer dn = (*it)->GetDataNode(); if (dn.IsNull()) { it = m_Interactors.erase(it); } else { DataInteractor::Pointer interactor = dn->GetDataInteractor(); if (interactor != it->GetPointer()) { it = m_Interactors.erase(it); } else { ++it; } } } } void mitk::Dispatcher::QueueEvent(InteractionEvent* event) { m_QueuedEvents.push_back(event); } void mitk::Dispatcher::SetEventProcessingMode(DataInteractor::Pointer dataInteractor) { m_ProcessingMode = dataInteractor->GetMode(); if (dataInteractor->GetMode() != REGULAR) { m_SelectedInteractor = dataInteractor; } } bool mitk::Dispatcher::HandleInternalEvent(InternalEvent* internalEvent) { if (internalEvent->GetSignalName() == IntDeactivateMe && internalEvent->GetTargetInteractor() != NULL) { internalEvent->GetTargetInteractor()->GetDataNode()->SetDataInteractor(NULL); internalEvent->GetTargetInteractor()->SetDataNode(NULL); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } return false; } diff --git a/Core/Code/Interactions/mitkDispatcher.h b/Core/Code/Interactions/mitkDispatcher.h index 8750937781..89a580d88e 100644 --- a/Core/Code/Interactions/mitkDispatcher.h +++ b/Core/Code/Interactions/mitkDispatcher.h @@ -1,129 +1,131 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkDispatcher_h #define mitkDispatcher_h -#include "itkObject.h" +#include "itkLightObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkDataNode.h" #include "mitkDataInteractor.h" #include #include +#include "mitkServiceTracker.h" namespace mitk { class InternalEvent; class InteractionEvent; - class InformerService; + struct InteractionEventObserver; /** * \class Dispatcher * \brief Manages event distribution * * Receives Events (Mouse-,Key-, ... Events) and dispatches them to the registered DataInteractor Objects. * The order in which DataInteractors are offered to handle an event is determined by layer of their associated DataNode. * Higher layers are preferred. * * \ingroup Interaction */ - class MITK_CORE_EXPORT Dispatcher: public itk::Object + class MITK_CORE_EXPORT Dispatcher: public itk::LightObject { public: - mitkClassMacro(Dispatcher, itk::Object); + mitkClassMacro(Dispatcher, itk::LightObject); itkNewMacro(Self); typedef std::list ListInteractorType; typedef std::list > ListEventsType; /** * To post new Events which are to be handled by the Dispatcher. * * @return Returns true if the event has been handled by an DataInteractor, and false else. */ bool ProcessEvent(InteractionEvent* event); /** * Adds an Event to the Dispatchers EventQueue, these events will be processed after a a regular posted event has been fully handled. - * This allows Interactors to post their own events without interrupting regular Dispatching workflow. - * NOTES: 1) If an event is added from an other source than an Interactor / Listener its execution will be delayed until the next regular event - * comes in. - * 2) Make sure you're not causing infinite loops! + * This allows DataInteractors to post their own events without interrupting regular Dispatching workflow. + * It is important to note that the queued events will be processed AFTER the state change of a current transition (which queued the events) + * is performed. * + * \note 1) If an event is added from an other source than an DataInteractor / Observer its execution will be delayed until the next regular event + * comes in. + * \note 2) Make sure you're not causing infinite loops! */ - void QueueEvent(InteractionEvent* event); /** * Adds the DataInteractor that is associated with the DataNode to the Dispatcher Queue. * If there already exists an DataInteractor that has a reference to the same DataNode, it is removed. * Note that within this method also all other DataInteractors are checked and removed if they are no longer active, * and were not removed properly. */ void AddDataInteractor(const DataNode* dataNode); /** * Remove all DataInteractors related to this Node, to prevent double entries and dead references. */ void RemoveDataInteractor(const DataNode* dataNode); size_t GetNumberOfInteractors(); // DEBUG TESTING protected: Dispatcher(); virtual ~Dispatcher(); private: struct cmp{ bool operator()(DataInteractor::Pointer d1, DataInteractor::Pointer d2){ return (d1->GetLayer() > d2->GetLayer()); } }; std::list m_Interactors; ListEventsType m_QueuedEvents; /** * Removes all Interactors without a DataNode pointing to them, this is necessary especially when a DataNode is assigned to a new Interactor */ void RemoveOrphanedInteractors(); /** * See \ref DispatcherEventDistSection for a description of ProcessEventModes */ ProcessEventMode m_ProcessingMode; DataInteractor::Pointer m_SelectedInteractor; void SetEventProcessingMode(DataInteractor::Pointer); /** * Function to handle special internal events, * such as events that are directed at a specific DataInteractor, * or the request to delete an Interactor and its DataNode. */ bool HandleInternalEvent(InternalEvent* internalEvent); /** - * Hold microservice reference to object that takes care of informing the EventObservers about InteractionEvents + * Hold microservice reference to object that takes care of informing the InteractionEventObservers about InteractionEvents */ - InformerService* m_InformerService; + mitk::ServiceTracker* m_EventObserverTracker; }; } /* namespace mitk */ #endif /* mitkDispatcher_h */ diff --git a/Core/Code/Interactions/mitkDisplayInteractor.cpp b/Core/Code/Interactions/mitkDisplayInteractor.cpp index 1e9a6bafc7..dc0a4fb335 100644 --- a/Core/Code/Interactions/mitkDisplayInteractor.cpp +++ b/Core/Code/Interactions/mitkDisplayInteractor.cpp @@ -1,345 +1,346 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDisplayInteractor.h" #include "mitkBaseRenderer.h" #include "mitkInteractionPositionEvent.h" #include "mitkPropertyList.h" #include // level window #include "mitkStandaloneDataStorage.h" #include "mitkNodePredicateDataType.h" #include "mitkLevelWindowProperty.h" #include "mitkLevelWindow.h" -void mitk::DisplayInteractor::Notify(InteractionEvent::Pointer interactionEvent, bool isHandled) +void mitk::DisplayInteractor::Notify(InteractionEvent* interactionEvent, bool isHandled) { // to use the state machine pattern, // the event is passed to the state machine interface to be handled if (!isHandled || m_AlwaysReact) { this->HandleEvent(interactionEvent, NULL); } } void mitk::DisplayInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("init", Init); CONNECT_FUNCTION("move", Move); CONNECT_FUNCTION("zoom", Zoom); CONNECT_FUNCTION("scroll", Scroll); CONNECT_FUNCTION("ScrollOneDown", ScrollOneDown); CONNECT_FUNCTION("ScrollOneUp", ScrollOneUp); CONNECT_FUNCTION("levelWindow", AdjustLevelWindow); } -mitk::DisplayInteractor::DisplayInteractor() +mitk::DisplayInteractor::DisplayInteractor() : + m_IndexToSliceModifier(4),m_AutoRepeat(false), m_AlwaysReact(false), m_ZoomFactor(2) { m_StartDisplayCoordinate.Fill(0); m_LastDisplayCoordinate.Fill(0); m_CurrentDisplayCoordinate.Fill(0); - m_IndexToSliceModifier = 4; - m_AlwaysReact = false; - m_AutoRepeat = false; - m_ZoomFactor = 2; } mitk::DisplayInteractor::~DisplayInteractor() { } bool mitk::DisplayInteractor::Init(StateMachineAction*, InteractionEvent* interactionEvent) { - BaseRenderer::Pointer sender = interactionEvent->GetSender(); + BaseRenderer* sender = interactionEvent->GetSender(); InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent == NULL) { MITK_WARN<< "DisplayVectorInteractor cannot process the event: " << interactionEvent->GetEventClass(); return false; } Vector2D origin = sender->GetDisplayGeometry()->GetOriginInMM(); double scaleFactorMMPerDisplayUnit = sender->GetDisplayGeometry()->GetScaleFactorMMPerDisplayUnit(); m_StartDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); m_StartCoordinateInMM = mitk::Point2D( (origin + m_StartDisplayCoordinate.GetVectorFromOrigin() * scaleFactorMMPerDisplayUnit).GetDataPointer()); return true; } bool mitk::DisplayInteractor::Move(StateMachineAction*, InteractionEvent* interactionEvent) { - BaseRenderer::Pointer sender = interactionEvent->GetSender(); + BaseRenderer* sender = interactionEvent->GetSender(); InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent == NULL) { MITK_WARN<< "DisplayVectorInteractor: cannot process the event in Move action: " << interactionEvent->GetEventClass(); return false; } // perform translation sender->GetDisplayGeometry()->MoveBy((positionEvent->GetPointerPositionOnScreen() - m_LastDisplayCoordinate) * (-1.0)); sender->GetRenderingManager()->RequestUpdate(sender->GetRenderWindow()); m_LastDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); return true; } bool mitk::DisplayInteractor::Zoom(StateMachineAction*, InteractionEvent* interactionEvent) { - BaseRenderer::Pointer sender = interactionEvent->GetSender(); + const BaseRenderer::Pointer sender = interactionEvent->GetSender(); InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent == NULL) { MITK_WARN<< "DisplayVectorInteractor cannot process the event: " << interactionEvent->GetEventClass(); return false; } float factor = 1.0; float distance = 0; if (m_ZoomDirection == "leftright") { distance = m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1]; } else { distance = m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0]; } // set zooming speed if (distance < 0.0) { factor = 1.0 / m_ZoomFactor; } else if (distance > 0.0) { factor = 1.0 * m_ZoomFactor; } sender->GetDisplayGeometry()->ZoomWithFixedWorldCoordinates(factor, m_StartDisplayCoordinate, m_StartCoordinateInMM); sender->GetRenderingManager()->RequestUpdate(sender->GetRenderWindow()); m_LastDisplayCoordinate = m_CurrentDisplayCoordinate; m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); return true; } bool mitk::DisplayInteractor::Scroll(StateMachineAction*, InteractionEvent* interactionEvent) { - BaseRenderer::Pointer sender = interactionEvent->GetSender(); InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent == NULL) { MITK_WARN<< "DisplayVectorInteractor::Scroll cannot process the event: " << interactionEvent->GetEventClass(); return false; } mitk::SliceNavigationController::Pointer sliceNaviController = interactionEvent->GetSender()->GetSliceNavigationController(); if (sliceNaviController) { int delta = 0; // Scrolling direction if (m_ScrollDirection == "leftright") { delta = static_cast(m_LastDisplayCoordinate[1] - positionEvent->GetPointerPositionOnScreen()[1]); } else { delta = static_cast(m_LastDisplayCoordinate[0] - positionEvent->GetPointerPositionOnScreen()[0]); } // Set how many pixels the mouse has to be moved to scroll one slice // if we moved less than 'm_IndexToSliceModifier' pixels slice ONE slice only if (delta > 0 && delta < m_IndexToSliceModifier) { delta = m_IndexToSliceModifier; } else if (delta < 0 && delta > -m_IndexToSliceModifier) { delta = -m_IndexToSliceModifier; } delta /= m_IndexToSliceModifier; int newPos = sliceNaviController->GetSlice()->GetPos() + delta; // if auto repeat is on, start at first slice if you reach the last slice and vice versa int maxSlices = sliceNaviController->GetSlice()->GetSteps(); if (m_AutoRepeat) { while (newPos < 0) { newPos += maxSlices; } while (newPos >= maxSlices) { newPos -= maxSlices; } } else { // if the new slice is below 0 we still show slice 0 // due to the stepper using unsigned int we have to do this ourselves if (newPos < 1) { newPos = 0; } } // set the new position sliceNaviController->GetSlice()->SetPos(newPos); m_LastDisplayCoordinate = m_CurrentDisplayCoordinate; m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); } return true; } bool mitk::DisplayInteractor::ScrollOneDown(StateMachineAction*, InteractionEvent* interactionEvent) { mitk::SliceNavigationController::Pointer sliceNaviController = interactionEvent->GetSender()->GetSliceNavigationController(); if (!sliceNaviController->GetSliceLocked()) { mitk::Stepper* stepper = sliceNaviController->GetSlice(); if (stepper->GetSteps() <= 1) { stepper = sliceNaviController->GetTime(); } stepper->Next(); } return true; } bool mitk::DisplayInteractor::ScrollOneUp(StateMachineAction*, InteractionEvent* interactionEvent) { mitk::SliceNavigationController::Pointer sliceNaviController = interactionEvent->GetSender()->GetSliceNavigationController(); if (!sliceNaviController->GetSliceLocked()) { mitk::Stepper* stepper = sliceNaviController->GetSlice(); if (stepper->GetSteps() <= 1) { stepper = sliceNaviController->GetTime(); } stepper->Previous(); return true; } return false; } bool mitk::DisplayInteractor::AdjustLevelWindow(StateMachineAction*, InteractionEvent* interactionEvent) { BaseRenderer::Pointer sender = interactionEvent->GetSender(); InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent == NULL) { MITK_WARN<< "DisplayVectorInteractor::Scroll cannot process the event: " << interactionEvent->GetEventClass(); return false; } m_LastDisplayCoordinate = m_CurrentDisplayCoordinate; m_CurrentDisplayCoordinate = positionEvent->GetPointerPositionOnScreen(); // search for active image mitk::DataStorage::Pointer storage = sender->GetDataStorage(); mitk::DataNode::Pointer node = NULL; mitk::DataStorage::SetOfObjects::ConstPointer allImageNodes = storage->GetSubset(mitk::NodePredicateDataType::New("Image")); for (unsigned int i = 0; i < allImageNodes->size(); i++) { bool isActiveImage = false; bool propFound = allImageNodes->at(i)->GetBoolProperty("imageForLevelWindow", isActiveImage); if (propFound && isActiveImage) { node = allImageNodes->at(i); continue; } } if (node.IsNull()) { node = storage->GetNode(mitk::NodePredicateDataType::New("Image")); } if (node.IsNull()) { return false; } mitk::LevelWindow lv = mitk::LevelWindow(); node->GetLevelWindow(lv); ScalarType level = lv.GetLevel(); ScalarType window = lv.GetWindow(); // calculate adjustments from mouse movements level += (m_CurrentDisplayCoordinate[0] - m_LastDisplayCoordinate[0]) * static_cast(2); window += (m_CurrentDisplayCoordinate[1] - m_LastDisplayCoordinate[1]) * static_cast(2); lv.SetLevelWindow(level, window); dynamic_cast(node->GetProperty("levelwindow"))->SetLevelWindow(lv); sender->GetRenderingManager()->RequestUpdateAll(); return true; } void mitk::DisplayInteractor::ConfigurationChanged() { mitk::PropertyList::Pointer properties = GetAttributes(); // auto repeat std::string strAutoRepeat = ""; if (properties->GetStringProperty("autoRepeat", strAutoRepeat)) { if (strAutoRepeat == "true") { m_AutoRepeat = true; } else { m_AutoRepeat = false; } } // pixel movement for scrolling one slice std::string strPixelPerSlice = ""; if (properties->GetStringProperty("pixelPerSlice", strPixelPerSlice)) { m_IndexToSliceModifier = atoi(strPixelPerSlice.c_str()); } else { m_IndexToSliceModifier = 4; } // scroll direction if (!properties->GetStringProperty("zoomDirection", m_ScrollDirection)) { m_ScrollDirection = "updown"; } // zoom direction if (!properties->GetStringProperty("zoomDirection", m_ZoomDirection)) { m_ZoomDirection = "updown"; } // zoom factor std::string strZoomFactor = ""; properties->GetStringProperty("zoomFactor", strZoomFactor); m_ZoomFactor = .05; if (atoi(strZoomFactor.c_str()) > 0) { m_ZoomFactor = 1.0 + (atoi(strZoomFactor.c_str()) / 100.0); } // allwaysReact std::string strAlwaysReact = ""; if (properties->GetStringProperty("alwaysReact", strAlwaysReact)) { if (strAlwaysReact == "true") { m_AlwaysReact = true; } else { m_AlwaysReact = false; } } else { m_AlwaysReact = false; } } + +bool mitk::DisplayInteractor::FilterEvents(InteractionEvent* /*interactionEvent*/, DataNode* /*dataNode*/) +{ + return true; +} diff --git a/Core/Code/Interactions/mitkDisplayInteractor.h b/Core/Code/Interactions/mitkDisplayInteractor.h index c78db7be66..4658a9127e 100644 --- a/Core/Code/Interactions/mitkDisplayInteractor.h +++ b/Core/Code/Interactions/mitkDisplayInteractor.h @@ -1,154 +1,163 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkDisplayInteractor_h #define mitkDisplayInteractor_h #include -#include "mitkEventObserver.h" +#include "mitkInteractionEventObserver.h" namespace mitk { /** *\class DisplayInteractor *@brief Observer that manages the interaction with the display. * - * This includes the interaction of Zooming, Panning and Scrolling. + * This includes the interaction of Zooming, Panning, Scrolling and adjusting the LevelWindow. * * @ingroup Interaction **/ /** - * Inherits from mitk::EventObserver since it doesn't alter any data (only their representation), - * and its actions cannot be associated with a DataNode. + * Inherits from mitk::InteractionEventObserver since it doesn't alter any data (only their representation), + * and its actions cannot be associated with a DataNode. Also inherits from EventStateMachine */ - class MITK_CORE_EXPORT DisplayInteractor: public EventObserver + class MITK_CORE_EXPORT DisplayInteractor: public EventStateMachine, public InteractionEventObserver { public: - mitkClassMacro(DisplayInteractor, StateMachine); - itkNewMacro(Self); + mitkClassMacro(DisplayInteractor, EventStateMachine) + itkNewMacro(Self) /** * By this function the Observer gets notifier about new events. * Here it is adapted to pass the events to the state machine in order to use * its infrastructure. * It also checks if event is to be accepted when i already has been processed by a DataInteractor. */ - virtual void Notify(InteractionEvent::Pointer interactionEvent, bool isHandled); + virtual void Notify(InteractionEvent* interactionEvent, bool isHandled); protected: DisplayInteractor(); virtual ~DisplayInteractor(); /** * Derived function. * Connects the action names used in the state machine pattern with functions implemented within - * this EventObserver. This is only necessary here because the events are processed by the state machine. + * this InteractionEventObserver. This is only necessary here because the events are processed by the state machine. */ void ConnectActionsAndFunctions(); /** * Derived function. * Is executed when config object is set / changed. * Here it is used to read out the parameters set in the configuration file, * and set the member variables accordingly. */ virtual void ConfigurationChanged(); + + /** + * Derived function. + * Is executed when config object is set / changed. + * Here it is used to read out the parameters set in the configuration file, + * and set the member variables accordingly. + */ + virtual bool FilterEvents(InteractionEvent* interactionEvent, DataNode* dataNode); + /** * \brief Initializes an interaction, saves the pointers start position for further reference. */ virtual bool Init(StateMachineAction*, InteractionEvent*); /** * \brief Performs panning of the data set in the render window. */ virtual bool Move(StateMachineAction*, InteractionEvent*); /** * \brief Performs zooming relative to mouse/pointer movement. * * Behavior is determined by \see m_ZoomDirection and \see m_ZoomFactor. * */ virtual bool Zoom(StateMachineAction*, InteractionEvent*); /** * \brief Performs scrolling relative to mouse/pointer movement. * * Behavior is determined by \see m_ScrollDirection and \see m_AutoRepeat. * */ virtual bool Scroll(StateMachineAction*, InteractionEvent*); /** * \brief Scrolls one layer up */ virtual bool ScrollOneDown(StateMachineAction*, InteractionEvent*); /** * \brief Scrolls one layer down */ virtual bool ScrollOneUp(StateMachineAction*, InteractionEvent*); /** * \brief Adjusts the level windows relative to mouse/pointer movement. */ virtual bool AdjustLevelWindow(StateMachineAction*, InteractionEvent*); private: /** * \brief Coordinate of the pointer at begin of an interaction */ mitk::Point2D m_StartDisplayCoordinate; /** * \brief Coordinate of the pointer at begin of an interaction translated to mm unit */ mitk::Point2D m_StartCoordinateInMM; /** * \brief Coordinate of the pointer in the last step within an interaction. */ mitk::Point2D m_LastDisplayCoordinate; /** * \brief Current coordinates of the pointer. */ mitk::Point2D m_CurrentDisplayCoordinate; /** * \brief Modifier that defines how many slices are scrolled per pixel that the mouse has moved * * This modifier defines how many slices the scene is scrolled per pixel that the mouse cursor has moved. * By default the modifier is 4. This means that when the user moves the cursor by 4 pixels in Y-direction * the scene is scrolled by one slice. If the user has moved the the cursor by 20 pixels, the scene is * scrolled by 5 slices. * * If the cursor has moved less than m_IndexToSliceModifier pixels the scene is scrolled by one slice. */ int m_IndexToSliceModifier; /** Defines behavior at end of data set. * If set to true it will restart at end of data set from the beginning. */ bool m_AutoRepeat; /** * Defines scroll behavior. * Default is up/down movement of pointer performs scrolling */ std::string m_ScrollDirection; /** * Defines scroll behavior. * Default is up/down movement of pointer performs zooming */ std::string m_ZoomDirection; /** * Determines if the Observer reacts to events that already have been processed by a DataInteractor. * The default value is false. */ bool m_AlwaysReact; /** * Factor to adjust zooming speed. */ float m_ZoomFactor; }; } #endif diff --git a/Core/Code/Interactions/mitkDisplayPositionEvent.cpp b/Core/Code/Interactions/mitkDisplayPositionEvent.cpp index 1884421ad6..8ee766820b 100644 --- a/Core/Code/Interactions/mitkDisplayPositionEvent.cpp +++ b/Core/Code/Interactions/mitkDisplayPositionEvent.cpp @@ -1,76 +1,76 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDisplayPositionEvent.h" #include "mitkBaseRenderer.h" mitk::DisplayPositionEvent::DisplayPositionEvent( mitk::BaseRenderer *sender, int type, int button, int buttonState, int key, const mitk::Point2D& displPosition ) : Event( sender, type, button, buttonState, key ), m_DisplayPosition( displPosition ), m_WorldPositionIsSet( false ), m_PickedObjectIsSet( false ) { } -const mitk::Point3D& mitk::DisplayPositionEvent::GetWorldPosition() const +mitk::Point3D &mitk::DisplayPositionEvent::GetWorldPosition() const { // Method performs position picking and sets world position if ( m_WorldPositionIsSet ) return m_WorldPosition; assert( m_Sender != NULL ); m_Sender->PickWorldPoint( m_DisplayPosition, m_WorldPosition ); m_WorldPositionIsSet = true; return m_WorldPosition; } mitk::DataNode *mitk::DisplayPositionEvent::GetPickedObjectNode() const { // Method performs object picking and sets both object and world position if ( m_PickedObjectIsSet ) { return m_PickedObjectNode; } assert( m_Sender != NULL ); m_PickedObjectNode = m_Sender->PickObject( m_DisplayPosition, m_WorldPosition ); m_PickedObjectIsSet = true; m_WorldPositionIsSet = true; return m_PickedObjectNode; } mitk::BaseData *mitk::DisplayPositionEvent::GetPickedObject() const { mitk::DataNode *node = this->GetPickedObjectNode(); if ( node != NULL ) { return node->GetData(); } else { return NULL; } } diff --git a/Core/Code/Interactions/mitkDisplayPositionEvent.h b/Core/Code/Interactions/mitkDisplayPositionEvent.h index 90ec265819..f3ed4377a3 100644 --- a/Core/Code/Interactions/mitkDisplayPositionEvent.h +++ b/Core/Code/Interactions/mitkDisplayPositionEvent.h @@ -1,80 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef DISPLAYPOSITIONEVENT_H_HEADER_INCLUDED_C184F366 #define DISPLAYPOSITIONEVENT_H_HEADER_INCLUDED_C184F366 #include #include "mitkEvent.h" #include "mitkVector.h" #include "mitkDataNode.h" namespace mitk { /** * \brief Event that stores coordinates * * Stores display position of the mouse. * * If requested, the correspondent 3D world position in mm is calculated via * picking (delegated to the BaseRenderer). Additionally, the mitk::BaseData or * mitk::DataNode corresponding to the picked object in the (3D) scene can * be retrieved. * \ingroup Interaction + * \deprecatedSince{2013_03} mitk::DisplayPositionEvent is deprecated. Use mitk::InteractionPositionEvent instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. */ class MITK_CORE_EXPORT DisplayPositionEvent : public Event { public: /** \brief Constructor with all necessary arguments. * * \param sender is the renderer that caused that event * \param type, button, buttonState, key: information from the Event * \param displPosition is the 2D Position of the mouse */ DisplayPositionEvent(BaseRenderer* sender, int type, int button, int buttonState, int key, const Point2D& displPosition); const Point2D& GetDisplayPosition() const { return m_DisplayPosition; } void SetDisplayPosition(const Point2D& displPosition) { m_DisplayPosition = displPosition; } - const Point3D& GetWorldPosition() const; + Point3D& GetWorldPosition() const; /** Returns node with object at the current position (NULL if not applicable) */ mitk::DataNode *GetPickedObjectNode() const; /** Returns object at the current position (NULL if not applicable) */ mitk::BaseData *GetPickedObject() const; protected: Point2D m_DisplayPosition; mutable Point3D m_WorldPosition; mutable bool m_WorldPositionIsSet; mutable mitk::DataNode::Pointer m_PickedObjectNode; mutable bool m_PickedObjectIsSet; }; typedef DisplayPositionEvent MouseEvent; } // namespace mitk #endif /* DISPLAYPOSITIONozsiEVENT_H_HEADER_INCLUDED_C184F366 */ diff --git a/Core/Code/Interactions/mitkEvent.h b/Core/Code/Interactions/mitkEvent.h index c68e7e05fe..a59464aee4 100644 --- a/Core/Code/Interactions/mitkEvent.h +++ b/Core/Code/Interactions/mitkEvent.h @@ -1,76 +1,80 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef EVENT_H_HEADER_INCLUDED_C1889CEE #define EVENT_H_HEADER_INCLUDED_C1889CEE #include namespace mitk { class BaseRenderer; //##Documentation //## @brief represents an Event with all its information //## //## Class, that stores mouse as well as key-events. Type stores the type of //## event, that has been activated (KeyPress, MouseMove...), Button and Key //## represent the cause of this event and ButtonState holds the Modifiers, //## that might have been pressed during the appearance of this event. //## Ether Button (Mouse) or Key (Keyboard) is set. if both are set //## accidentally then the button is accepted. //## @ingroup Interaction + /** + * \deprecatedSince{2013_03} mitk::Event is deprecated. Use mitk::InteractionEvent instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ class MITK_CORE_EXPORT Event { public: //##Documentation //## @param sender Needed for DisplayCoordinateOperation in DisplayVectorInteractor....???? if not needed, then set on NULL //## @param type Type of Event: Mouse or Key Event? (look in mitkInteractionConst.h) //## @param button Mouse button //## @param buttonState Which other key has been pressed? (Mouse/Keyboard modifier-keys) //## @param key Pressed key Event(mitk::BaseRenderer* sender, int type, int button, int buttonState, int key); virtual ~Event(); mitk::BaseRenderer* GetSender() const; int GetType() const; int GetButton() const; int GetKey() const; bool operator==(const Event& event) const; int GetButtonState() const; protected: mitk::BaseRenderer* m_Sender; int m_Type; int m_Button; int m_ButtonState; int m_Key; }; } // namespace mitk #endif /* EVENT_H_HEADER_INCLUDED_C1889CEE */ diff --git a/Core/Code/Interactions/mitkEventConfig.cpp b/Core/Code/Interactions/mitkEventConfig.cpp index 80afa068ae..19c869a8c5 100755 --- a/Core/Code/Interactions/mitkEventConfig.cpp +++ b/Core/Code/Interactions/mitkEventConfig.cpp @@ -1,196 +1,196 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkEventConfig.h" #include #include #include #include #include #include "mitkEventFactory.h" #include "mitkInteractionEvent.h" #include "mitkInternalEvent.h" #include "mitkInteractionKeyEvent.h" #include "mitkInteractionEventConst.h" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include "mitkModuleResourceStream.h" #include "mitkModuleRegistry.h" namespace mitk { vtkStandardNewMacro(EventConfig); } -mitk::EventConfig::EventConfig() -:m_Errors(false) +mitk::EventConfig::EventConfig() : + m_Errors(false) { if (m_PropertyList.IsNull()) { m_PropertyList = PropertyList::New(); } } mitk::EventConfig::~EventConfig() { } void mitk::EventConfig::InsertMapping(EventMapping mapping) { for (EventListType::iterator it = m_EventList.begin(); it != m_EventList.end(); ++it) { if ((*it).interactionEvent->MatchesTemplate(mapping.interactionEvent)) { - MITK_INFO<< "Configuration overwritten:" << (*it).variantName; + //MITK_INFO<< "Configuration overwritten:" << (*it).variantName; m_EventList.erase(it); break; } } m_EventList.push_back(mapping); } /** * @brief Loads the xml file filename and generates the necessary instances. **/ bool mitk::EventConfig::LoadConfig(std::string fileName, std::string moduleName) { mitk::Module* module = mitk::ModuleRegistry::GetModule(moduleName); mitk::ModuleResource resource = module->GetResource("Interactions/" + fileName); if (!resource.IsValid()) { mitkThrow()<< ("Resource not valid. State machine pattern not found:" + fileName); } mitk::ModuleResourceStream stream(resource); this->SetStream(&stream); return this->Parse() && !m_Errors; } void mitk::EventConfig::StartElement(const char* elementName, const char **atts) { std::string name(elementName); if (name == xmlTagConfigRoot) { // } else if (name == xmlTagParam) { std::string name = ReadXMLStringAttribut(xmlParameterName, atts); std::string value = ReadXMLStringAttribut(xmlParameterValue, atts); m_PropertyList->SetStringProperty(name.c_str(), value.c_str()); } - else if (name == xmlTagInput) + else if (name == xmlTagEventVariant) { std::string eventClass = ReadXMLStringAttribut(xmlParameterEventClass, atts); - std::string eventVariant = ReadXMLStringAttribut(xmlParameterEventVariant, atts); + std::string eventVariant = ReadXMLStringAttribut(xmlParameterName, atts); // New list in which all parameters are stored that are given within the tag m_EventPropertyList = PropertyList::New(); m_EventPropertyList->SetStringProperty(xmlParameterEventClass.c_str(), eventClass.c_str()); m_EventPropertyList->SetStringProperty(xmlParameterEventVariant.c_str(), eventVariant.c_str()); m_CurrEventMapping.variantName = eventVariant; } else if (name == xmlTagAttribute) { // Attributes that describe an Input Event, such as which MouseButton triggered the event,or which modifier keys are pressed std::string name = ReadXMLStringAttribut(xmlParameterName, atts); std::string value = ReadXMLStringAttribut(xmlParameterValue, atts); m_EventPropertyList->SetStringProperty(name.c_str(), value.c_str()); } } void mitk::EventConfig::EndElement(const char* elementName) { std::string name(elementName); // At end of input section, all necessary infos are collected to created an interaction event. - if (name == xmlTagInput) + if (name == xmlTagEventVariant) { InteractionEvent::Pointer event = EventFactory::CreateEvent(m_EventPropertyList); if (event.IsNotNull()) { m_CurrEventMapping.interactionEvent = event; InsertMapping(m_CurrEventMapping); } else { MITK_WARN<< "EventConfig: Unknown Event-Type in config. Entry skipped: " << name; } } } std::string mitk::EventConfig::ReadXMLStringAttribut(std::string name, const char** atts) { if (atts) { const char** attsIter = atts; while (*attsIter) { if (name == *attsIter) { attsIter++; return *attsIter; } attsIter += 2; } } return std::string(); } -const mitk::PropertyList::Pointer mitk::EventConfig::GetAttributes() +mitk::PropertyList::Pointer mitk::EventConfig::GetAttributes() const { return m_PropertyList; } -std::string mitk::EventConfig::GetMappedEvent(InteractionEvent* interactionEvent) +std::string mitk::EventConfig::GetMappedEvent(InteractionEvent::Pointer interactionEvent) { // internal events are excluded from mapping if (interactionEvent->GetEventClass() == "InternalEvent") { - InternalEvent* internalEvent = dynamic_cast(interactionEvent); + InternalEvent* internalEvent = dynamic_cast(interactionEvent.GetPointer()); return internalEvent->GetSignalName(); } for (EventListType::iterator it = m_EventList.begin(); it != m_EventList.end(); ++it) { if ((*it).interactionEvent->MatchesTemplate(interactionEvent)) { return (*it).variantName; } } // if this part is reached, no mapping has been found, // so here we handle key events and map a key event to the string "Std" + letter/code // so "A" will be returned as "StdA" if (interactionEvent->GetEventClass() == "KeyEvent") { - InteractionKeyEvent* keyEvent = dynamic_cast(interactionEvent); + InteractionKeyEvent* keyEvent = dynamic_cast(interactionEvent.GetPointer()); return ("Std" + keyEvent->GetKey()); } return ""; } void mitk::EventConfig::ClearConfig() { m_EventList.clear(); } bool mitk::EventConfig::ReadXMLBooleanAttribut(std::string name, const char** atts) { std::string s = ReadXMLStringAttribut(name, atts); std::transform(s.begin(), s.end(), s.begin(), ::toupper); return s == "TRUE"; } diff --git a/Core/Code/Interactions/mitkEventConfig.h b/Core/Code/Interactions/mitkEventConfig.h index b79cbd0502..2f41a6640d 100755 --- a/Core/Code/Interactions/mitkEventConfig.h +++ b/Core/Code/Interactions/mitkEventConfig.h @@ -1,139 +1,144 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkStateMachineConfig_h #define mitkStateMachineConfig_h #include #include -#include "itkObject.h" - -#include "itkObjectFactory.h" #include "mitkCommon.h" #include #include #include namespace mitk { class InteractionEvent; + class EventConfigReader: public vtkXMLParser + { + public: + + private: + }; + /** * \class EventConfig * \brief Configuration Object for Statemachines. * * Reads given config file, which translates specific user inputs (InteractionEvents) into EventVariants that can be processed * by the StateMachine. * Refer to \ref ConfigFileDescriptionSection . * * @ingroup Interaction **/ - class MITK_CORE_EXPORT EventConfig: public vtkXMLParser + class EventConfig: public vtkXMLParser { public: static EventConfig *New(); - vtkTypeMacro(EventConfig,vtkXMLParser); + vtkTypeMacro(EventConfig,vtkXMLParser) + typedef itk::SmartPointer EventType; /** - * @brief Loads XML resource - * - * Loads a XML resource file in the given module context. - * The files have to be placed in the Resources/Interaction folder of their respective module. - **/ + * @brief Loads XML resource + * + * Loads a XML resource file in the given module context. + * The files have to be placed in the Resources/Interaction folder of their respective module. + **/ bool LoadConfig(std::string fileName, std::string moduleName = "Mitk"); void ClearConfig(); /** * Returns a PropertyList that contains the properties set in the configuration file. * All properties are stored as strings. */ - const PropertyList::Pointer GetAttributes(); + PropertyList::Pointer GetAttributes() const; /** - * Checks if the config object has a definition for the given event. If it has the corresponding variant name is return, else + * Checks if the config object has a definition for the given event. If it has, the corresponding variant name is returned, else * an empty string is returned. * \note mitk::InternalEvents are handled differently. Their signal name is returned as event variant. So there is no need * to configure them in a config file. - * \note mitk::InteractionKeys my have a defined event variant, if this is the case, this function returns it. If no + * \note mitk::InteractionKeys may have a defined event variant, if this is the case, this function returns it. If no * such definition is found key events are mapped to Std + Key , so an 'A' will be return as 'StdA' . */ - std::string GetMappedEvent(InteractionEvent* interactionEvent); + std::string GetMappedEvent(EventType interactionEvent); protected: EventConfig(); virtual ~EventConfig(); /** * @brief Derived from XMLReader **/ void StartElement(const char* elementName, const char **atts); /** * @brief Derived from XMLReader **/ void EndElement(const char* elementName); private: /** * @brief Derived from XMLReader **/ std::string ReadXMLStringAttribut(std::string name, const char** atts); /** * @brief Derived from XMLReader **/ bool ReadXMLBooleanAttribut(std::string name, const char** atts); - /** * @brief List of all global properties of the config object. */ PropertyList::Pointer m_PropertyList; /** * @brief Temporal list of all properties of a Event. Used to parse an Input-Event and collect all parameters between the two - * and tags. + * and tags. */ PropertyList::Pointer m_EventPropertyList; struct EventMapping { std::string variantName; EventType interactionEvent; }; + /** * Checks if mapping with the same parameters already exists, if so, it is replaced, * else the new mapping added */ void InsertMapping(EventMapping mapping); typedef std::list EventListType; EventMapping m_CurrEventMapping; /** * Stores InteractionEvents and their corresponding VariantName */ EventListType m_EventList; bool m_Errors; // use member, because of inheritance from vtkXMLParser we can't return a success value for parsing the file. }; } // namespace mitk #endif /* mitkStateMachineConfig_h */ diff --git a/Core/Code/Interactions/mitkEventDescription.h b/Core/Code/Interactions/mitkEventDescription.h index 46fa633d3e..fc660a62df 100644 --- a/Core/Code/Interactions/mitkEventDescription.h +++ b/Core/Code/Interactions/mitkEventDescription.h @@ -1,60 +1,66 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef EVENTDESCRIPTION_H_HEADER_INCLUDED_C188FC4D #define EVENTDESCRIPTION_H_HEADER_INCLUDED_C188FC4D #include #include "mitkEvent.h" #include #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4251) #endif namespace mitk { //##Documentation //## @brief adds additional Information (Name and EventID) to an Event //## //## A name and an ID is added to the information of an event, so the event can //## be processed futher on. //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} EventDescription is deprecated. It will become obsolete. + * All necessary information is now store in the event classes derived from mitk::InteractionEvent . + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ class MITK_CORE_EXPORT EventDescription : public Event { public: EventDescription(int type, int button, int buttonState,int key, std::string name, int id); std::string GetName() const; int GetId() const; private: std::string m_Name; int m_Id; }; } // namespace mitk #ifdef _MSC_VER # pragma warning(pop) #endif #endif /* EVENTDESCRIPTION_H_HEADER_INCLUDED_C188FC4D */ diff --git a/Core/Code/Interactions/mitkEventFactory.cpp b/Core/Code/Interactions/mitkEventFactory.cpp index 2aeb5eeaa5..9fcc7d3078 100755 --- a/Core/Code/Interactions/mitkEventFactory.cpp +++ b/Core/Code/Interactions/mitkEventFactory.cpp @@ -1,222 +1,224 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkEventFactory.h" #include #include #include #include #include #include #include #include #include #include #include - -std::vector &mitk::EventFactory::split(const std::string &s, char delim, std::vector &elems) +namespace { - std::stringstream ss(s); - std::string item; - while (std::getline(ss, item, delim)) + std::vector &split(const std::string &s, char delim, std::vector &elems) { - elems.push_back(item); + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) + { + elems.push_back(item); + } + return elems; } - return elems; -} -std::vector mitk::EventFactory::split(const std::string &s, char delim) -{ - std::vector elems; - return split(s, delim, elems); + std::vector split(const std::string &s, char delim) + { + std::vector < std::string > elems; + return split(s, delim, elems); + } } mitk::InteractionEvent::Pointer mitk::EventFactory::CreateEvent(PropertyList::Pointer list) { - // +// std::string eventClass, eventVariant; list->GetStringProperty(xmlParameterEventClass.c_str(), eventClass); list->GetStringProperty(xmlParameterEventVariant.c_str(), eventVariant); - // Query all possible attributes, if they are not present, set their default values. - // Position Events & Key Events +// Query all possible attributes, if they are not present, set their default values. +// Position Events & Key Events std::string strModifiers; ModifierKeys modifiers = NoKey; std::string strEventButton; MouseButtons eventButton = NoButton; std::string strButtonState; MouseButtons buttonState = NoButton; std::string strKey; std::string key; std::string strWheelDelta; int wheelDelta; std::string strSignalName = ""; Point2D pos; pos.Fill(0); - // Parse modifier information +// Parse modifier information if (list->GetStringProperty(xmlEventPropertyModifier.c_str(), strModifiers)) { std::vector mods = split(strModifiers, ','); for (std::vector::iterator it = mods.begin(); it != mods.end(); ++it) { std::transform((*it).begin(), (*it).end(), (*it).begin(), ::toupper); if (*it == "CTRL") { modifiers = modifiers | ControlKey; } else if (*it == "ALT") { modifiers = modifiers | AltKey; } else if (*it == "SHIFT") { modifiers = modifiers | ShiftKey; } else { MITK_WARN<< "mitkEventFactory: Invalid event modifier in config file :" << (*it); } } } - // Set EventButton +// Set EventButton if (list->GetStringProperty(xmlEventPropertyEventButton.c_str(), strEventButton)) { std::transform(strEventButton.begin(), strEventButton.end(), strEventButton.begin(), ::toupper); if (strEventButton == "MIDDLEMOUSEBUTTON") { eventButton = MiddleMouseButton; } else if (strEventButton == "LEFTMOUSEBUTTON") { eventButton = LeftMouseButton; } else if (strEventButton == "RIGHTMOUSEBUTTON") { eventButton = RightMouseButton; } else { MITK_WARN<< "mitkEventFactory: Invalid event button in config file: " << strEventButton; } } - // Parse ButtonStates +// Parse ButtonStates if (list->GetStringProperty(xmlEventPropertyButtonState.c_str(), strButtonState)) { std::vector mods = split(strButtonState, ','); for (std::vector::iterator it = mods.begin(); it != mods.end(); ++it) { std::transform((*it).begin(), (*it).end(), (*it).begin(), ::toupper); if (*it == "MIDDLEMOUSEBUTTON") { buttonState = buttonState | MiddleMouseButton; } else if (*it == "LEFTMOUSEBUTTON") { buttonState = buttonState | LeftMouseButton; } else if (*it == "RIGHTMOUSEBUTTON") { buttonState = buttonState | RightMouseButton; } else { MITK_WARN<< "mitkEventFactory: Invalid event buttonstate in config file:" << (*it); } } } - // Key +// Key if (!list->GetStringProperty(xmlEventPropertyKey.c_str(), strKey)) { key = ""; } else { key = strKey; } - // WheelDelta +// WheelDelta if (!list->GetStringProperty(xmlEventPropertyScrollDirection.c_str(), strWheelDelta)) { wheelDelta = 0; } else { std::transform(strWheelDelta.begin(), strWheelDelta.end(), strWheelDelta.begin(), ::toupper); if (strWheelDelta == "DOWN") { wheelDelta = -1; } else { wheelDelta = 1; } } - // Internal Signals Name +// Internal Signals Name list->GetStringProperty(xmlEventPropertySignalName.c_str(), strSignalName); /* * Here the objects are created */ mitk::InteractionEvent::Pointer event; std::transform(eventClass.begin(), eventClass.end(), eventClass.begin(), ::toupper); if (eventClass == "MOUSEPRESSEVENT") { // buttonstates incorporate the event button (as in Qt) buttonState = buttonState | eventButton; event = MousePressEvent::New(NULL, pos, buttonState, modifiers, eventButton); } else if (eventClass == "MOUSEMOVEEVENT") { event = MouseMoveEvent::New(NULL, pos, buttonState, modifiers); } else if (eventClass == "MOUSERELEASEEVENT") { event = MouseReleaseEvent::New(NULL, pos, buttonState, modifiers, eventButton); } else if (eventClass == "KEYEVENT") { event = InteractionKeyEvent::New(NULL, key, modifiers); } else if (eventClass == "MOUSEWHEELEVENT") { event = MouseWheelEvent::New(NULL, pos, buttonState, modifiers, wheelDelta); } else if (eventClass == "POSITIONEVENT") { event = InteractionPositionEvent::New(NULL, pos, "PositionEvent"); } else if (eventClass == "INTERNALEVENT") { event = InternalEvent::New(NULL, NULL, strSignalName); } else if (eventClass == "INTERACTIONEVENT") { event = InteractionEvent::New(NULL, strSignalName); } if (event.IsNull()) { MITK_WARN<< "Event couldn't be constructed. Please check your StateMachine patterns and config files\n for the following event class, which is not valid: " << eventClass; return NULL; } return event; } diff --git a/Core/Code/Interactions/mitkEventFactory.h b/Core/Code/Interactions/mitkEventFactory.h index f9d10c9bfd..3b4efe2504 100755 --- a/Core/Code/Interactions/mitkEventFactory.h +++ b/Core/Code/Interactions/mitkEventFactory.h @@ -1,52 +1,47 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkEventFactory_h #define mitkEventFactory_h -#include "itkObject.h" -#include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEvent.h" #include "mitkPropertyList.h" #include namespace mitk { /** * \class EventFactory * \brief Generates InteractionEvent-Objects which are described by a PropertyList. - * This call is used by the EventConfig object to parse configuration files and create Events based on the xml description. + * This class is used by the EventConfig object to parse configuration files and create Events based on the xml description. * * \ingroup Interaction */ - class MITK_CORE_EXPORT EventFactory: public itk::Object + class MITK_CORE_EXPORT EventFactory { public: /** * Parses PropertyList and queries all possible Information. * If an attribute is not present the default value is used. * Finally the Event-Type is chosen by the ClassName property and the object is created using the collected information. */ static InteractionEvent::Pointer CreateEvent(PropertyList::Pointer eventDescription); - private: - static std::vector &split(const std::string &s, char delim, std::vector &elems); - static std::vector split(const std::string &s, char delim); }; } #endif /* mitkEventFactory_h */ diff --git a/Core/Code/Interactions/mitkEventInformer.h b/Core/Code/Interactions/mitkEventInformer.h index 24602e173c..7aa3432720 100644 --- a/Core/Code/Interactions/mitkEventInformer.h +++ b/Core/Code/Interactions/mitkEventInformer.h @@ -1,43 +1,43 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkEventInformer_h #define mitkEventInformer_h -#include "mitkEventObserver.h" +#include "mitkInteractionEventObserver.h" #include "mitkInteractionEvent.h" #include namespace mitk { /** - * Serves as an interface for the micro service that takes care of informing/registering EventObserver + * Serves as an interface for the micro service that takes care of informing/registering InteractionEventObserver */ struct EventInformerService { virtual ~EventInformerService() { } - virtual void RegisterObserver(EventObserver::Pointer eventObserver) = 0; - virtual void UnRegisterObserver(EventObserver::Pointer eventObserver) = 0; + virtual void RegisterObserver(InteractionEventObserver::Pointer InteractionEventObserver) = 0; + virtual void UnRegisterObserver(InteractionEventObserver::Pointer InteractionEventObserver) = 0; virtual void NotifyObservers(InteractionEvent::Pointer interactionEvent) = 0; }; } /* namespace mitk */ US_DECLARE_SERVICE_INTERFACE(mitk::EventInformerService, "EventInformerService/1.0") #endif diff --git a/Core/Code/Interactions/mitkEventMapper.cpp b/Core/Code/Interactions/mitkEventMapper.cpp index 113851f947..82db98a890 100644 --- a/Core/Code/Interactions/mitkEventMapper.cpp +++ b/Core/Code/Interactions/mitkEventMapper.cpp @@ -1,708 +1,706 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /** * EventMapping: * This class maps the Events, usually given by the OS or here by QT, to a MITK internal EventId. * It loads all information from the xml-file (possible, understandable Events with the mitkEventID). * If an event appears, the method MapEvent is called with the event params. * This Method looks up the event params, and tries to find an mitkEventId to it. * If yes, then sends the event and the found ID to the globalStateMachine, which handles all * further operations of that event. * */ #include "mitkEventMapper.h" #include "mitkInteractionConst.h" #include "mitkStateEvent.h" #include "mitkOperationEvent.h" #include "mitkGlobalInteraction.h" #include #include "mitkStandardFileLocations.h" //#include #include "mitkConfig.h" #include "mitkCoreObjectFactory.h" #include #include #include #include // us #include "mitkModule.h" #include "mitkModuleResource.h" #include "mitkModuleResourceStream.h" #include "mitkModuleRegistry.h" +#include +#include namespace mitk { vtkStandardNewMacro(EventMapper); } #ifdef MBI_INTERNAL_CONFERENCE #include #include #include #include #include #endif //MBI_INTERNAL_CONFERENCE //XML Event const std::string mitk::EventMapper::STYLE = "STYLE"; const std::string mitk::EventMapper::NAME = "NAME"; const std::string mitk::EventMapper::ID = "ID"; const std::string mitk::EventMapper::TYPE = "TYPE"; const std::string mitk::EventMapper::BUTTON = "BUTTON"; const std::string mitk::EventMapper::BUTTONSTATE = "BUTTONSTATE"; const std::string mitk::EventMapper::KEY = "KEY"; const std::string mitk::EventMapper::EVENTS = "events"; const std::string mitk::EventMapper::EVENT = "event"; mitk::EventMapper::EventDescriptionVec mitk::EventMapper::m_EventDescriptions; std::string mitk::EventMapper::m_XmlFileName; mitk::StateEvent mitk::EventMapper::m_StateEvent; std::string mitk::EventMapper::m_StyleName; struct ltstr { bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; } }; mitk::EventMapper::EventMapper() { //map with string to key for mapping string from xml-file to int m_EventConstMap["Type_None"] = mitk::Type_None; // invalid event m_EventConstMap["Type_Timer"] = mitk::Type_Timer; // timer event m_EventConstMap["Type_MouseButtonPress"] = mitk::Type_MouseButtonPress; // mouse button pressed m_EventConstMap["Type_MouseButtonRelease"] = mitk::Type_MouseButtonRelease; // mouse button released m_EventConstMap["Type_MouseButtonDblClick"] = mitk::Type_MouseButtonDblClick; // mouse button double click m_EventConstMap["Type_MouseMove"] = mitk::Type_MouseMove; // mouse move m_EventConstMap["Type_KeyPress"] = mitk::Type_KeyPress; // key pressed m_EventConstMap["Type_KeyRelease"] = mitk::Type_KeyRelease; // key released m_EventConstMap["Type_FocusIn"] = 8; // keyboard focus received m_EventConstMap["Type_FocusOut"] = 9; // keyboard focus lost m_EventConstMap["Type_Enter"] = 10; // mouse enters widget m_EventConstMap["Type_Leave"] = 11; // mouse leaves widget m_EventConstMap["Type_Paint"] = 12; // paint widget m_EventConstMap["Type_Move"] = 13; // move widget m_EventConstMap["Type_Resize"] = 14; // resize widget m_EventConstMap["Type_Create"] = 15; // after object creation m_EventConstMap["Type_Destroy"] = 16; // during object destruction m_EventConstMap["Type_Show"] = 17; // widget is shown m_EventConstMap["Type_Hide"] = 18; // widget is hidden m_EventConstMap["Type_Close"] = 19; // request to close widget m_EventConstMap["Type_Quit"] = 20; // request to quit application m_EventConstMap["Type_Reparent"] = 21; // widget has been reparented m_EventConstMap["Type_ShowMinimized"] = 22; // widget is shown minimized m_EventConstMap["Type_ShowNormal"] = 23; // widget is shown normal m_EventConstMap["Type_WindowActivate"] = 24; // window was activated m_EventConstMap["Type_WindowDeactivate"] = 25; // window was deactivated m_EventConstMap["Type_ShowToParent"] = 26; // widget is shown to parent m_EventConstMap["Type_HideToParent"] = 27; // widget is hidden to parent m_EventConstMap["Type_ShowMaximized"] = 28; // widget is shown maximized m_EventConstMap["Type_ShowFullScreen"] = 29; // widget is shown full-screen m_EventConstMap["Type_Accel"] = 30; // accelerator event m_EventConstMap["Type_Wheel"] = 31; // wheel event m_EventConstMap["Type_AccelAvailable"] = 32; // accelerator available event m_EventConstMap["Type_CaptionChange"] = 33; // caption changed m_EventConstMap["Type_IconChange"] = 34; // icon changed m_EventConstMap["Type_ParentFontChange"] = 35; // parent font changed m_EventConstMap["Type_ApplicationFontChange"] = 36;// application font changed m_EventConstMap["Type_ParentPaletteChange"] = 37; // parent palette changed m_EventConstMap["Type_ApplicationPaletteChange"] = 38;// application palette changed m_EventConstMap["Type_PaletteChange"] = 39; // widget palette changed m_EventConstMap["Type_Clipboard"] = 40; // internal clipboard event m_EventConstMap["Type_Speech"] = 42; // reserved for speech input m_EventConstMap["Type_SockAct"] = 50; // socket activation m_EventConstMap["Type_AccelOverride"] = 51; // accelerator override event m_EventConstMap["Type_DeferredDelete"] = 52; // deferred delete event m_EventConstMap["Type_DragEnter"] = 60; // drag moves into widget m_EventConstMap["Type_DragMove"] = 61; // drag moves in widget m_EventConstMap["Type_DragLeave"] = 62; // drag leaves or is cancelled m_EventConstMap["Type_Drop"] = 63; // actual drop m_EventConstMap["Type_DragResponse"] = 64; // drag accepted/rejected m_EventConstMap["Type_ChildInserted"] = 70; // new child widget m_EventConstMap["Type_ChildRemoved"] = 71; // deleted child widget m_EventConstMap["Type_LayoutHint"] = 72; // child min/max size changed m_EventConstMap["Type_ShowWindowRequest"] = 73; // widget's window should be mapped m_EventConstMap["Type_ActivateControl"] = 80; // ActiveX activation m_EventConstMap["Type_DeactivateControl"] = 81; // ActiveX deactivation m_EventConstMap["Type_ContextMenu"] = 82; // context popup menu m_EventConstMap["Type_IMStart"] = 83; // input method composition start m_EventConstMap["Type_IMCompose"] = 84; // input method composition m_EventConstMap["Type_IMEnd"] = 85; // input method composition end m_EventConstMap["Type_Accessibility"] = 86; // accessibility information is requested m_EventConstMap["Type_TabletMove"] = 87; // Wacom tablet event m_EventConstMap["Type_LocaleChange"] = 88; // the system locale changed m_EventConstMap["Type_LanguageChange"] = 89; // the application language changed m_EventConstMap["Type_LayoutDirectionChange"] = 90; // the layout direction changed m_EventConstMap["Type_Style"] = 91; // internal style event m_EventConstMap["Type_TabletPress"] = 92; // tablet press m_EventConstMap["Type_TabletRelease"] = 93; // tablet release // apparently not necessary, since the IDs can be assigned earlier (in the AddOns after they are generated in the driver) //m_EventConstMap["Type_TDMouseInput"] = mitk::Type_TDMouseInput; // 3D mouse input occured m_EventConstMap["Type_User"] = 1000; // first user event id m_EventConstMap["Type_MaxUser"] = 65535; // last user event id //ButtonState m_EventConstMap["BS_NoButton"] = mitk::BS_NoButton;//0x0000 m_EventConstMap["BS_LeftButton"] = mitk::BS_LeftButton;//0x0001 m_EventConstMap["BS_RightButton"] = mitk::BS_RightButton;//0x0002 m_EventConstMap["BS_MidButton"] = mitk::BS_MidButton;//0x0004 m_EventConstMap["BS_MouseButtonMask"] = mitk::BS_MouseButtonMask;//0x0007 m_EventConstMap["BS_ShiftButton"] = mitk::BS_ShiftButton;//0x0008 m_EventConstMap["BS_ControlButton"] = mitk::BS_ControlButton;//0x0010 m_EventConstMap["BS_AltButton"] = mitk::BS_AltButton;//0x0020 m_EventConstMap["BS_KeyButtonMask"] = mitk::BS_KeyButtonMask;//0x0038 m_EventConstMap["BS_Keypad"] = mitk::BS_Keypad;//0x4000 //Modifier m_EventConstMap["Mod_SHIFT"] = 0x00200000; m_EventConstMap["Mod_CTRL"] = 0x00400000; m_EventConstMap["Mod_ALT"] = 0x00800000; m_EventConstMap["Mod_MODIFIER_MASK"] = 0x00e00000; m_EventConstMap["Mod_UNICODE_ACCEL"] = 0x10000000; m_EventConstMap["Mod_ASCII_ACCEL"] = 0x10000000; //Key m_EventConstMap["Key_Escape"] = 0x1000; m_EventConstMap["Key_Tab"] = 0x1001; m_EventConstMap["Key_Backtab"] = 0x1002; m_EventConstMap["Key_BackTab"] = 0x1002; m_EventConstMap["Key_Backspace"] = 0x1003; m_EventConstMap["Key_BackSpace"] = 0x1003; m_EventConstMap["Key_Return"] = 0x1004; m_EventConstMap["Key_Enter"] = 0x1005; m_EventConstMap["Key_Insert"] = 0x1006; m_EventConstMap["Key_Delete"] = 0x1007; m_EventConstMap["Key_Pause"] = 0x1008; m_EventConstMap["Key_Print"] = 0x1009; m_EventConstMap["Key_SysReq"] = 0x100a; m_EventConstMap["Key_Home"] = 0x1010; m_EventConstMap["Key_End"] = 0x1011; m_EventConstMap["Key_Left"] = 0x1012; m_EventConstMap["Key_Up"] = 0x1013; m_EventConstMap["Key_Right"] = 0x1014; m_EventConstMap["Key_Down"] = 0x1015; m_EventConstMap["Key_Prior"] = 0x1016; m_EventConstMap["Key_PageUp"] = 0x1016; m_EventConstMap["Key_Next"] = 0x1017; m_EventConstMap["Key_PageDown"] = 0x1017; m_EventConstMap["Key_Shift"] = 0x1020; m_EventConstMap["Key_Control"] = 0x1021; m_EventConstMap["Key_Meta"] = 0x1022; m_EventConstMap["Key_Alt"] = 0x1023; m_EventConstMap["Key_CapsLock"] = 0x1024; m_EventConstMap["Key_NumLock"] = 0x1025; m_EventConstMap["Key_ScrollLock"] = 0x1026; m_EventConstMap["Key_F1"] = 0x1030; m_EventConstMap["Key_F2"] = 0x1031; m_EventConstMap["Key_F3"] = 0x1032; m_EventConstMap["Key_F4"] = 0x1033; m_EventConstMap["Key_F5"] = 0x1034; m_EventConstMap["Key_F6"] = 0x1035; m_EventConstMap["Key_F7"] = 0x1036; m_EventConstMap["Key_F8"] = 0x1037; m_EventConstMap["Key_F9"] = 0x1038; m_EventConstMap["Key_F10"] = 0x1039; m_EventConstMap["Key_F11"] = 0x103a; m_EventConstMap["Key_F12"] = 0x103b; m_EventConstMap["Key_F13"] = 0x103c; m_EventConstMap["Key_F14"] = 0x103d; m_EventConstMap["Key_F15"] = 0x103e; m_EventConstMap["Key_F16"] = 0x103f; m_EventConstMap["Key_F17"] = 0x1040; m_EventConstMap["Key_F18"] = 0x1041; m_EventConstMap["Key_F19"] = 0x1042; m_EventConstMap["Key_F20"] = 0x1043; m_EventConstMap["Key_F21"] = 0x1044; m_EventConstMap["Key_F22"] = 0x1045; m_EventConstMap["Key_F23"] = 0x1046; m_EventConstMap["Key_F24"] = 0x1047; m_EventConstMap["Key_F25"] = 0x1048; m_EventConstMap["Key_F26"] = 0x1049; m_EventConstMap["Key_F27"] = 0x104a; m_EventConstMap["Key_F28"] = 0x104b; m_EventConstMap["Key_F29"] = 0x104c; m_EventConstMap["Key_F30"] = 0x104d; m_EventConstMap["Key_F31"] = 0x104e; m_EventConstMap["Key_F32"] = 0x104f; m_EventConstMap["Key_F33"] = 0x1050; m_EventConstMap["Key_F34"] = 0x1051; m_EventConstMap["Key_F35"] = 0x1052; m_EventConstMap["Key_Super_L"] = 0x1053; m_EventConstMap["Key_Super_R"] = 0x1054; m_EventConstMap["Key_Menu"] = 0x1055; m_EventConstMap["Key_Hyper_L"] = 0x1056; m_EventConstMap["Key_Hyper_R"] = 0x1057; m_EventConstMap["Key_Help"] = 0x1058; m_EventConstMap["Key_Muhenkan"] = 0x1122; m_EventConstMap["Key_Henkan"] = 0x1123; m_EventConstMap["Key_Hiragana_Katakana"] = 0x1127; m_EventConstMap["Key_Zenkaku_Hankaku"] = 0x112A; m_EventConstMap["Key_Space"] = 0x20; m_EventConstMap["Key_Any"] = 0x20; m_EventConstMap["Key_Exclam"] = 0x21; m_EventConstMap["Key_QuoteDbl"] = 0x22; m_EventConstMap["Key_NumberSign"] = 0x23; m_EventConstMap["Key_Dollar"] = 0x24; m_EventConstMap["Key_Percent"] = 0x25; m_EventConstMap["Key_Ampersand"] = 0x26; m_EventConstMap["Key_Apostrophe"] = 0x27; m_EventConstMap["Key_ParenLeft"] = 0x28; m_EventConstMap["Key_ParenRight"] = 0x29; m_EventConstMap["Key_Asterisk"] = 0x2a; m_EventConstMap["Key_Plus"] = 0x2b; m_EventConstMap["Key_Comma"] = 0x2c; m_EventConstMap["Key_Minus"] = 0x2d; m_EventConstMap["Key_Period"] = 0x2e; m_EventConstMap["Key_Slash"] = 0x2f; m_EventConstMap["Key_0"] = 0x30; m_EventConstMap["Key_1"] = 0x31; m_EventConstMap["Key_2"] = 0x32; m_EventConstMap["Key_3"] = 0x33; m_EventConstMap["Key_4"] = 0x34; m_EventConstMap["Key_5"] = 0x35; m_EventConstMap["Key_6"] = 0x36; m_EventConstMap["Key_7"] = 0x37; m_EventConstMap["Key_8"] = 0x38; m_EventConstMap["Key_9"] = 0x39; m_EventConstMap["Key_Colon"] = 0x3a; m_EventConstMap["Key_Semicolon"] = 0x3b; m_EventConstMap["Key_Less"] = 0x3c; m_EventConstMap["Key_Equal"] = 0x3d; m_EventConstMap["Key_Greater"] = 0x3e; m_EventConstMap["Key_Question"] = 0x3f; m_EventConstMap["Key_At"] = 0x40; m_EventConstMap["Key_A"] = 0x41; m_EventConstMap["Key_B"] = 0x42; m_EventConstMap["Key_C"] = 0x43; m_EventConstMap["Key_D"] = 0x44; m_EventConstMap["Key_E"] = 0x45; m_EventConstMap["Key_F"] = 0x46; m_EventConstMap["Key_G"] = 0x47; m_EventConstMap["Key_H"] = 0x48; m_EventConstMap["Key_I"] = 0x49; m_EventConstMap["Key_J"] = 0x4a; m_EventConstMap["Key_K"] = 0x4b; m_EventConstMap["Key_L"] = 0x4c; m_EventConstMap["Key_M"] = 0x4d; m_EventConstMap["Key_N"] = 0x4e; m_EventConstMap["Key_O"] = 0x4f; m_EventConstMap["Key_P"] = 0x50; m_EventConstMap["Key_Q"] = 0x51; m_EventConstMap["Key_R"] = 0x52; m_EventConstMap["Key_S"] = 0x53; m_EventConstMap["Key_T"] = 0x54; m_EventConstMap["Key_U"] = 0x55; m_EventConstMap["Key_V"] = 0x56; m_EventConstMap["Key_W"] = 0x57; m_EventConstMap["Key_X"] = 0x58; m_EventConstMap["Key_Y"] = 0x59; m_EventConstMap["Key_Z"] = 0x5a; m_EventConstMap["Key_BracketLeft"] = 0x5b; m_EventConstMap["Key_Backslash"] = 0x5c; m_EventConstMap["Key_BracketRight"] = 0x5d; m_EventConstMap["Key_AsciiCircum"] = 0x5e; m_EventConstMap["Key_Underscore"] = 0x5f; m_EventConstMap["Key_QuoteLeft"] = 0x60; m_EventConstMap["Key_BraceLeft"] = 0x7b; m_EventConstMap["Key_Bar"] = 0x7c; m_EventConstMap["Key_BraceRight"] = 0x7d; m_EventConstMap["Key_AsciiTilde"] = 0x7e; m_EventConstMap["Key_nobreakspace"] = 0x0a0; m_EventConstMap["Key_exclamdown"] = 0x0a1; m_EventConstMap["Key_cent"] = 0x0a2; m_EventConstMap["Key_sterling"] = 0x0a3; m_EventConstMap["Key_currency"] = 0x0a4; m_EventConstMap["Key_yen"] = 0x0a5; m_EventConstMap["Key_brokenbar"] = 0x0a6; m_EventConstMap["Key_section"] = 0x0a7; m_EventConstMap["Key_diaeresis"] = 0x0a8; m_EventConstMap["Key_copyright"] = 0x0a9; m_EventConstMap["Key_ordfeminine"] = 0x0aa; m_EventConstMap["Key_guillemotleft"] = 0x0ab; m_EventConstMap["Key_notsign"] = 0x0ac; m_EventConstMap["Key_hyphen"] = 0x0ad; m_EventConstMap["Key_registered"] = 0x0ae; m_EventConstMap["Key_macron"] = 0x0af; m_EventConstMap["Key_degree"] = 0x0b0; m_EventConstMap["Key_plusminus"] = 0x0b1; m_EventConstMap["Key_twosuperior"] = 0x0b2; m_EventConstMap["Key_threesuperior"] = 0x0b3; m_EventConstMap["Key_acute"] = 0x0b4; m_EventConstMap["Key_mu"] = 0x0b5; m_EventConstMap["Key_paragraph"] = 0x0b6; m_EventConstMap["Key_periodcentered"] = 0x0b7; m_EventConstMap["Key_cedilla"] = 0x0b8; m_EventConstMap["Key_onesuperior"] = 0x0b9; m_EventConstMap["Key_masculine"] = 0x0ba; m_EventConstMap["Key_guillemotright"] = 0x0bb; m_EventConstMap["Key_onequarter"] = 0x0bc; m_EventConstMap["Key_onehalf"] = 0x0bd; m_EventConstMap["Key_threequarters"] = 0x0be; m_EventConstMap["Key_questiondown"] = 0x0bf; m_EventConstMap["Key_Agrave"] = 0x0c0; m_EventConstMap["Key_Aacute"] = 0x0c1; m_EventConstMap["Key_Acircumflex"] = 0x0c2; m_EventConstMap["Key_Atilde"] = 0x0c3; m_EventConstMap["Key_Adiaeresis"] = 0x0c4; m_EventConstMap["Key_Aring"] = 0x0c5; m_EventConstMap["Key_AE"] = 0x0c6; m_EventConstMap["Key_Ccedilla"] = 0x0c7; m_EventConstMap["Key_Egrave"] = 0x0c8; m_EventConstMap["Key_Eacute"] = 0x0c9; m_EventConstMap["Key_Ecircumflex"] = 0x0ca; m_EventConstMap["Key_Ediaeresis"] = 0x0cb; m_EventConstMap["Key_Igrave"] = 0x0cc; m_EventConstMap["Key_Iacute"] = 0x0cd; m_EventConstMap["Key_Icircumflex"] = 0x0ce; m_EventConstMap["Key_Idiaeresis"] = 0x0cf; m_EventConstMap["Key_ETH"] = 0x0d0; m_EventConstMap["Key_Ntilde"] = 0x0d1; m_EventConstMap["Key_Ograve"] = 0x0d2; m_EventConstMap["Key_Oacute"] = 0x0d3; m_EventConstMap["Key_Ocircumflex"] = 0x0d4; m_EventConstMap["Key_Otilde"] = 0x0d5; m_EventConstMap["Key_Odiaeresis"] = 0x0d6; m_EventConstMap["Key_multiply"] = 0x0d7; m_EventConstMap["Key_Ooblique"] = 0x0d8; m_EventConstMap["Key_Ugrave"] = 0x0d9; m_EventConstMap["Key_Uacute"] = 0x0da; m_EventConstMap["Key_Ucircumflex"] = 0x0db; m_EventConstMap["Key_Udiaeresis"] = 0x0dc; m_EventConstMap["Key_Yacute"] = 0x0dd; m_EventConstMap["Key_THORN"] = 0x0de; m_EventConstMap["Key_ssharp"] = 0x0df; m_EventConstMap["Key_agrave"] = 0x0e0; m_EventConstMap["Key_aacute"] = 0x0e1; m_EventConstMap["Key_acircumflex"] = 0x0e2; m_EventConstMap["Key_atilde"] = 0x0e3; m_EventConstMap["Key_adiaeresis"] = 0x0e4; m_EventConstMap["Key_aring"] = 0x0e5; m_EventConstMap["Key_ae"] = 0x0e6; m_EventConstMap["Key_ccedilla"] = 0x0e7; m_EventConstMap["Key_egrave"] = 0x0e8; m_EventConstMap["Key_eacute"] = 0x0e9; m_EventConstMap["Key_ecircumflex"] = 0x0ea; m_EventConstMap["Key_ediaeresis"] = 0x0eb; m_EventConstMap["Key_igrave"] = 0x0ec; m_EventConstMap["Key_iacute"] = 0x0ed; m_EventConstMap["Key_icircumflex"] = 0x0ee; m_EventConstMap["Key_idiaeresis"] = 0x0ef; m_EventConstMap["Key_eth"] = 0x0f0; m_EventConstMap["Key_ntilde"] = 0x0f1; m_EventConstMap["Key_ograve"] = 0x0f2; m_EventConstMap["Key_oacute"] = 0x0f3; m_EventConstMap["Key_ocircumflex"] = 0x0f4; m_EventConstMap["Key_otilde"] = 0x0f5; m_EventConstMap["Key_odiaeresis"] = 0x0f6; m_EventConstMap["Key_division"] = 0x0f7; m_EventConstMap["Key_oslash"] = 0x0f8; m_EventConstMap["Key_ugrave"] = 0x0f9; m_EventConstMap["Key_uacute"] = 0x0fa; m_EventConstMap["Key_ucircumflex"] = 0x0fb; m_EventConstMap["Key_udiaeresis"] = 0x0fc; m_EventConstMap["Key_yacute"] = 0x0fd; m_EventConstMap["Key_thorn"] = 0x0fe; m_EventConstMap["Key_ydiaeresis"] = 0x0ff; m_EventConstMap["Key_unknown"] = 0xffff; m_EventConstMap["Key_none"] = 0xffff; } mitk::EventMapper::~EventMapper() { } //##Documentation //## searches for the event in m_EventDescription and adds the corresponding eventID //## bool mitk::EventMapper::MapEvent(Event* event, GlobalInteraction* globalInteraction, int mitkPostedEventID ) { int eventID = mitkPostedEventID; if( mitkPostedEventID == 0 ) { //search the event in the list of event descriptions, if found, then take the number and produce a stateevent EventDescriptionVecIter iter; for (iter = m_EventDescriptions.begin(); iter!=m_EventDescriptions.end();iter++) { if (*iter == *event) break; } if (iter == m_EventDescriptions.end())//not found return false; eventID = (*iter).GetId(); } //set the Menger_Var m_StateEvent and send to StateMachine, which does everything further! m_StateEvent.Set( eventID, event ); /* Group and Object EventId: then EventMapper has the power to decide which operations hang together; each event causes n (n e N) operations (e.g. StateChanges, data-operations...). Undo must recall all these coherent operations, so all of the same objectId. But Undo has also the power to recall more operationsets, for example a set for building up a new object, so that a newly build up object is deleted after a Undo and not only the latest set point. The StateMachines::ExecuteAction have the power to descide weather a new GroupID has to be calculated (by example after the editing of a new object) A user interaction with the mouse is started by a mousePressEvent, continues with a MouseMove and finishes with a MouseReleaseEvent */ switch (event->GetType()) { case mitk::Type_MouseButtonPress://Increase mitk::OperationEvent::IncCurrObjectEventId(); break; case mitk::Type_MouseMove://same break; case mitk::Type_MouseButtonRelease://same break; case mitk::Type_User://same break; case mitk::Type_KeyPress://Increase mitk::OperationEvent::IncCurrObjectEventId(); break; default://increase mitk::OperationEvent::IncCurrObjectEventId(); } #ifdef MBI_INTERNAL_CONFERENCE //Conference - pass local events through if ( mitkPostedEventID == 0 ) { mitk::CoreObjectFactory::GetInstance()->MapEvent(event,eventID); } #endif //MBI_INTERNAL_CONFERENCE mitk::OperationEvent::ExecuteIncrement(); if ( globalInteraction != NULL ) { return globalInteraction->HandleEvent( &m_StateEvent ); } else { return mitk::GlobalInteraction::GetInstance()->HandleEvent(&m_StateEvent); } } bool mitk::EventMapper::LoadBehavior(std::string fileName) { if ( fileName.empty() ) return false; if (m_XmlFileName.length() > 0) { if (fileName.compare(m_XmlFileName) == 0) return true; // this is nothing bad, we already loaded this file. } this->SetFileName( fileName.c_str() ); m_XmlFileName = fileName.c_str(); return ( this->Parse() ); } bool mitk::EventMapper::LoadBehaviorString(std::string xmlString) { if ( xmlString.empty() ) return false; return ( this->Parse(xmlString.c_str(), xmlString.length()) ); } bool mitk::EventMapper::LoadStandardBehavior() { Module* module = ModuleRegistry::GetModule("Mitk"); - if (module == NULL) { - mitkThrow()<< ("Module Mitk unavailable." ); - return false; - } ModuleResource resource = module->GetResource("Interactions/Legacy/StateMachine.xml"); if (!resource.IsValid()) { mitkThrow()<< ("Resource not valid. State machine pattern not found:Interactions/Legacy/StateMachine.xml" ); } mitk::ModuleResourceStream stream(resource); std::string patternString((std::istreambuf_iterator(stream)), std::istreambuf_iterator()); - return LoadBehaviorString(patternString); + return this->LoadBehaviorString(patternString); } //##Documentation //## @brief converts the given const String declared in the xml-file //## to the defined const int inline int mitk::EventMapper::convertConstString2ConstInt(std::string input) { ConstMapIter tempIt = m_EventConstMap.find(input.c_str()); if (tempIt != m_EventConstMap.end()) { return (tempIt)->second; } //mitk::StatusBar::GetInstance()->DisplayText("Warning! from mitkEventMapper.cpp: Couldn't find matching Event Int from Event String in XML-File"); return -1;//for didn't find anything } void mitk::EventMapper::StartElement (const char *elementName, const char **atts) { if ( elementName == EVENT ) { // EventDescription(int type, int button, int buttonState,int key, std::string name, int id) EventDescription eventDescr( convertConstString2ConstInt( ReadXMLStringAttribut( TYPE, atts )), convertConstString2ConstInt( ReadXMLStringAttribut( BUTTON, atts )), ReadXMLIntegerAttribut( BUTTONSTATE, atts ), convertConstString2ConstInt( ReadXMLStringAttribut( KEY, atts )), ReadXMLStringAttribut( NAME, atts ), ReadXMLIntegerAttribut( ID, atts )); //check for a double entry unless it is an event for internal usage if (eventDescr.GetType()!= mitk::Type_User) { for (EventDescriptionVecIter iter = m_EventDescriptions.begin(); iter!=m_EventDescriptions.end(); iter++) { if (*iter == eventDescr) { MITK_DEBUG << "Event description " << eventDescr.GetName() << " already present! Skipping event description"; return; } } } m_EventDescriptions.push_back(eventDescr); } else if ( elementName == EVENTS ) m_StyleName = ReadXMLStringAttribut( STYLE, atts ); } std::string mitk::EventMapper::GetStyleName() const { return m_StyleName; } std::string mitk::EventMapper::ReadXMLStringAttribut( std::string name, const char** atts ) { if(atts) { const char** attsIter = atts; while(*attsIter) { if ( name == *attsIter ) { attsIter++; return *attsIter; } attsIter++; attsIter++; } } return std::string(); } int mitk::EventMapper::ReadXMLIntegerAttribut( std::string name, const char** atts ) { std::string s = ReadXMLStringAttribut( name, atts ); static const std::string hex = "0x"; int result; if ( s[0] == hex[0] && s[1] == hex[1] ) result = strtol( s.c_str(), NULL, 16 ); else result = atoi( s.c_str() ); return result; } void mitk::EventMapper::SetStateEvent(mitk::Event* event) { m_StateEvent.Set( m_StateEvent.GetId(), event ); } bool mitk::EventMapper::RefreshStateEvent(mitk::StateEvent* stateEvent) { //search the event within stateEvent in the list of event descriptions, if found adapt stateEvent ID EventDescriptionVecIter iter; for (iter = m_EventDescriptions.begin(); iter!=m_EventDescriptions.end(); iter++) { if (*iter == *(stateEvent->GetEvent())) break; } if (iter != m_EventDescriptions.end())//found { stateEvent->Set((*iter).GetId(), stateEvent->GetEvent()); return true; } else return false; return false; } void mitk::EventMapper::AddEventMapperAddOn(mitk::EventMapperAddOn* newAddOn) { bool addOnAlreadyAdded = false; for(AddOnVectorType::const_iterator it = this->m_AddOnVector.begin();it != m_AddOnVector.end();it++) { if(*it == newAddOn) { addOnAlreadyAdded = true; break; } } if(!addOnAlreadyAdded) { m_AddOnVector.push_back(newAddOn); MITK_INFO << "AddOn Count: " << m_AddOnVector.size(); } } void mitk::EventMapper::RemoveEventMapperAddOn(mitk::EventMapperAddOn* unusedAddOn) { for(AddOnVectorType::iterator it = this->m_AddOnVector.begin();it != m_AddOnVector.end();it++) { if(*it == unusedAddOn) { m_AddOnVector.erase(it); break; } } } diff --git a/Core/Code/Interactions/mitkEventMapper.h b/Core/Code/Interactions/mitkEventMapper.h index 169e23f1f9..e94f2d88f3 100644 --- a/Core/Code/Interactions/mitkEventMapper.h +++ b/Core/Code/Interactions/mitkEventMapper.h @@ -1,201 +1,208 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef EVENTMAPPER_H_HEADER_INCLUDED #define EVENTMAPPER_H_HEADER_INCLUDED #include #include #include #include #include #include #include namespace mitk { struct ltstr { bool operator()(const char* s1, const char* s2) const { return strcmp(s1, s2) < 0; } }; typedef std::string msgString; //for friendship wor to set the stateevent after calculating class GlobalInteraction; class StateMachine; class StateEvent; class EventMapperAddOn; //##Documentation //## @brief Maps an Event to its description //## //## EventMapping: //## This class mapps the Events, usually given by the OS or here by QT, to a MITK internal EventId. //## It loads all information from the xml-file (possible, understandable Events with the mitkEventID). //## If an event appears, the method MapEvent is called with the event params. //## This Method looks up the event params, and tries to find an mitkEventId to it. //## If yes, then sends the event and the found ID to the globalStateMachine, which handles all //## further operations of that event. //## For Undo-Mechanism a statechanging StateMachine::HandleEvent is connected to an ObjectEventID and an GroupEventId. //## That way a fine an raw Undo is possible (fine for ObjectID by ObjectID, raw for GroupID for GroupID) //## Here the ObjectEventID gets increased, //## not the GroupEventId(must get increased by a StateMachine, that has the information when a new Group of operation starts) //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} EventMapper is deprecated. It will become obsolete. + * Mapping from Qt to MITK events is performed now by mitk::QmitkRenderWindow . + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT EventMapper : public vtkXMLParser { public: static EventMapper *New(); vtkTypeMacro(EventMapper,vtkXMLParser); typedef std::vector EventDescriptionVec; typedef std::vector::iterator EventDescriptionVecIter; typedef std::map ConstMap; typedef std::map::iterator ConstMapIter; typedef std::vector< itk::SmartPointer > AddOnVectorType; //##Documentation //## searches the Event in m_EventDescription //## and if included transmits the event to globalInteraction. //## If specified, a custom instance of GlobalInteraction will be used, //## otherwise the method will retrieve the default (singleton) instance. //## the optional parameter should be used in a conference to avoid a //## feedback static bool MapEvent(Event* event, GlobalInteraction* globalInteraction = NULL, int mitkPostedEventID=0 ); //##Documentation //## Searches for the event within stateEvent in the internal map of event descriptions //## If entry found the stateEvent ID is adapted //## maps the Event in m_EventDescription with the ID //## and if found returns true, //## if not found it returns false static bool RefreshStateEvent(StateEvent* stateEvent); //##Documentation //## loads an XML-File containing events and adds definition to internal mapping list //## //## Several files can be loaded. Event descriptions have to be unique or a warning will be displayed. //## If the same file is loaded twice, //## it will only be parsed the first time. //## If a file A, then a file B and then file A is to be loaded, warnings //## will be displayed when loading file A the second time. bool LoadBehavior(std::string fileName); //##Documentation //## loads Events into m_EventDescriptions from xml string //## also involved: EventMapper::startEvent(...) bool LoadBehaviorString(std::string xmlString); //##Documentation //## Try to load standard behavior file "StateMachine.xml" //## //## Search strategy: //## \li try environment variable "MITKCONF" (path to "StateMachine.xml") //## \li try "./StateMachine.xml" //## \li try via source directory (using MITKROOT from cmake-created //## mitkConfig.h) "MITKROOT/Interactions/mitkBaseInteraction/StateMachine.xml" bool LoadStandardBehavior(); //##Documentation //## reads a Tag from an XML-file //## adds Events to m_EventDescription std::string GetStyleName() const; //friendship because of SetStateEvent for computing WorldCoordinates friend class mitk::GlobalInteraction; /** * @brief adds a new EventMapper addon */ void AddEventMapperAddOn(mitk::EventMapperAddOn* newAddOn); /** * @brief removes an EventMapper addon */ void RemoveEventMapperAddOn(mitk::EventMapperAddOn* unusedAddOn); protected: EventMapper(); ~EventMapper(); //##Documentation //##@brief method only for GlobalInteraction to change the Event (from DiplayPositionEvent to PositionEvent) static void SetStateEvent(Event* event); private: //##Documentation //## @brief method used in XLM-Reading; gets called when a start-tag is read void StartElement (const char *elementName, const char **atts); //##Documentation //## @brief reads an XML-String-Attribute std::string ReadXMLStringAttribut( std::string name, const char** atts); //##Documentation //## @brief reads an XML-Integer-Attribute int ReadXMLIntegerAttribut( std::string name, const char** atts ); //##Documentation //## @brief converts the strings given by the XML-Behaviour-File to int inline int convertConstString2ConstInt(std::string input); //static std::string Convert2String(int input); //static std::string Convert2String(double input); //static std::string Convert2String(float input); //##Documentation //## @brief maps the strings to int for convertion from XML-Behaviour-File ConstMap m_EventConstMap; //##Documentation //## @brief stores the information for the connection between QT-Events and the internal EventId. //## gets this information from xml-File static EventDescriptionVec m_EventDescriptions; static std::string m_XmlFileName; static StateEvent m_StateEvent; //##Documentation //## @brief stores the name of the Event-Style loaded static std::string m_StyleName; static const std::string STYLE; static const std::string NAME; static const std::string ID; static const std::string TYPE; static const std::string BUTTON; static const std::string BUTTONSTATE; static const std::string KEY; static const std::string EVENTS; static const std::string EVENT; /** * @brief all available EventMapper addons consisting of one or more input devices */ AddOnVectorType m_AddOnVector; }; } // namespace mitk #endif /* EVENTMAPPER_H_HEADER_INCLUDED_C187864A */ diff --git a/Core/Code/Interactions/mitkEventStateMachine.cpp b/Core/Code/Interactions/mitkEventStateMachine.cpp index fe64b217c4..233f19ddd7 100644 --- a/Core/Code/Interactions/mitkEventStateMachine.cpp +++ b/Core/Code/Interactions/mitkEventStateMachine.cpp @@ -1,148 +1,148 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkEventStateMachine.h" #include "mitkStateMachineContainer.h" #include "mitkInteractionEvent.h" #include "mitkStateMachineAction.h" #include "mitkStateMachineTransition.h" #include "mitkStateMachineState.h" // us #include "mitkModule.h" #include "mitkModuleResource.h" #include "mitkModuleResourceStream.h" #include "mitkModuleRegistry.h" -mitk::EventStateMachine::EventStateMachine() +mitk::EventStateMachine::EventStateMachine() : + m_StateMachineContainer(NULL), m_CurrentState(NULL) { - m_StateMachineContainer = NULL; - m_CurrentState = NULL; } -bool mitk::EventStateMachine::LoadStateMachine(std::string filename, std::string moduleName) +bool mitk::EventStateMachine::LoadStateMachine(const std::string filename, const std::string moduleName) { if (m_StateMachineContainer != NULL) { m_StateMachineContainer->Delete(); } m_StateMachineContainer = StateMachineContainer::New(); - if (m_StateMachineContainer->LoadBehavior(filename,moduleName)) + if (m_StateMachineContainer->LoadBehavior(filename, moduleName)) { m_CurrentState = m_StateMachineContainer->GetStartState(); // clear actions map ,and connect all actions as declared in sub-class m_ActionFunctionsMap.clear(); ConnectActionsAndFunctions(); return true; } else { MITK_WARN<< "Unable to load StateMachine from file: " << filename; return false; } } mitk::EventStateMachine::~EventStateMachine() { if (m_StateMachineContainer != NULL) { m_StateMachineContainer->Delete(); } } -void mitk::EventStateMachine::AddActionFunction(std::string action, mitk::TActionFunctor* functor) +void mitk::EventStateMachine::AddActionFunction(const std::string action, mitk::TActionFunctor* functor) { if (!functor) return; // make sure double calls for same action won't cause memory leaks delete m_ActionFunctionsMap[action]; m_ActionFunctionsMap[action] = functor; } bool mitk::EventStateMachine::HandleEvent(InteractionEvent* event, DataNode* dataNode) { if (!FilterEvents(event, dataNode)) { return false; } // check if the current state holds a transition that works with the given event. StateMachineTransition::Pointer transition = m_CurrentState->GetTransition(event->GetEventClass(), MapToEventVariant(event)); if (transition.IsNotNull()) { // iterate over all actions in this transition and execute them ActionVectorType actions = transition->GetActions(); bool success = false; for (ActionVectorType::iterator it = actions.begin(); it != actions.end(); ++it) { success |= ExecuteAction(*it, event); // treat an event as handled if at least one of the actions is executed successfully } if (success || actions.empty()) // an empty action list is always successful { // perform state change m_CurrentState = transition->GetNextState(); //MITK_INFO<< "StateChange: " << m_CurrentState->GetName(); } return success; } else { return false; // no transition found that matches event } } void mitk::EventStateMachine::ConnectActionsAndFunctions() { MITK_WARN<< "ConnectActionsAndFunctions in DataInteractor not implemented.\n DataInteractor will not be able to process any events."; } bool mitk::EventStateMachine::ExecuteAction(StateMachineAction* action, InteractionEvent* event) { if (action == NULL) { return false; } // Maps Action-Name to Functor and executes DoAction on Functor. TActionFunctor* actionFunction = m_ActionFunctionsMap[action->GetActionName()]; if (actionFunction == NULL) { return false; } bool retVal = actionFunction->DoAction(action, event); return retVal; } mitk::StateMachineState* mitk::EventStateMachine::GetCurrentState() { return m_CurrentState.GetPointer(); } bool mitk::EventStateMachine::FilterEvents(InteractionEvent* interactionEvent, DataNode* dataNode) { - if (dataNode == NULL) { - MITK_WARN << "EventStateMachine: Empty DataNode received along with this Event " << interactionEvent; + if (dataNode == NULL) + { + MITK_WARN<< "EventStateMachine: Empty DataNode received along with this Event " << interactionEvent; return false; } bool visible = false; if (dataNode->GetPropertyList()->GetBoolProperty("visible", visible) == false) { //property doesn't exist return false; } return visible; } diff --git a/Core/Code/Interactions/mitkEventStateMachine.h b/Core/Code/Interactions/mitkEventStateMachine.h index 26266be58d..f4152a0a50 100644 --- a/Core/Code/Interactions/mitkEventStateMachine.h +++ b/Core/Code/Interactions/mitkEventStateMachine.h @@ -1,176 +1,176 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKEVENTSTATEMACHINE_H_ #define MITKEVENTSTATEMACHINE_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" -#include "mitkEventHandler.h" +#include "mitkInteractionEventHandler.h" #include #include namespace mitk { class StateMachineContainer; class StateMachineAction; class InteractionEvent; class StateMachineState; class DataNode; /** * \class TActionFunctor * \brief Base class of ActionFunctors, to provide an easy to connect actions with functions. */ class MITK_CORE_EXPORT TActionFunctor { public: virtual bool DoAction(StateMachineAction*, InteractionEvent*)=0; virtual ~TActionFunctor() { } }; /** * \class TSpecificActionFunctor * Specific implementation of ActionFunctor class, implements a reference to the function which is to be executed. It takes two arguments: * StateMachineAction - the action by which the function call is invoked, InteractionEvent - the event that caused the transition. */ template class TSpecificActionFunctor: public TActionFunctor { public: TSpecificActionFunctor(T* object, bool (T::*memberFunctionPointer)(StateMachineAction*, InteractionEvent*)) : m_Object(object), m_MemberFunctionPointer(memberFunctionPointer) { } virtual ~TSpecificActionFunctor() { } virtual bool DoAction(StateMachineAction* action, InteractionEvent* event) { return (*m_Object.*m_MemberFunctionPointer)(action, event);// executes member function } private: T* m_Object; bool (T::*m_MemberFunctionPointer)(StateMachineAction*, InteractionEvent*); }; /** Macro that can be used to connect a StateMachineAction with a function. * It assumes that there is a typedef Classname Self in classes that use this macro, as is provided by e.g. mitkClassMacro */ #define CONNECT_FUNCTION(a, f) \ EventStateMachine::AddActionFunction(a, new TSpecificActionFunctor(this, &Self::f)); /** * \class EventStateMachine * * \brief Super-class that provides the functionality of a StateMachine to DataInteractors. * * A state machine is created by loading a state machine pattern. It consists of states, transitions and action. * The state represent the current status of the interaction, transitions are means to switch between states. Each transition * is triggered by an event and it is associated with actions that are to be executed when the state change is performed. * */ - class MITK_CORE_EXPORT EventStateMachine: public virtual EventHandler + class MITK_CORE_EXPORT EventStateMachine : public mitk::InteractionEventHandler { public: - mitkClassMacro(EventStateMachine, EventHandler); - itkNewMacro(Self); + mitkClassMacro(EventStateMachine, InteractionEventHandler) + itkNewMacro(Self) typedef std::map ActionFunctionsMapType; typedef itk::SmartPointer StateMachineStateType; /** * @brief Loads XML resource * * Loads a XML resource file in the given module context. * Default is the Mitk module (core). * The files have to be placed in the Resources/Interaction folder of their respective module. **/ - bool LoadStateMachine(std::string filename, std::string moduleName="Mitk"); + bool LoadStateMachine(const std::string filename, const std::string moduleName="Mitk"); /** * Receives Event from Dispatcher. * Event is mapped using the EventConfig Object to a variant, then it is checked if the StateMachine is listening for * such an Event. If this is the case, the transition to the next state it performed and all actions associated with the transition executed, * and true is returned to the caller. * If the StateMachine can't handle this event false is returned. * Attention: * If a transition is associated with multiple actions - "true" is returned if one action returns true, * and the event is treated as HANDLED even though some actions might not have been executed! So be sure that all actions that occur within * one transitions have the same conditions. */ bool HandleEvent(InteractionEvent* event, DataNode* dataNode); protected: EventStateMachine(); virtual ~EventStateMachine(); /** * Connects action from StateMachine (String in XML file) with a function that is called when this action is to be executed. */ - void AddActionFunction(std::string action, TActionFunctor* functor); + void AddActionFunction(const std::string action, TActionFunctor* functor); StateMachineState* GetCurrentState(); /** * Is called after loading a statemachine. * Overwrite this function in specific interactor implementations. * Connect actions and functions using the CONNECT_FUNCTION macro within this function. */ virtual void ConnectActionsAndFunctions(); /** * Looks up function that is associated with action and executes it. * To implement your own execution scheme overwrite this in your DataInteractor. */ virtual bool ExecuteAction(StateMachineAction* action, InteractionEvent* interactionEvent); /** * Implements filter scheme for events. * Standard implementation accepts events from 2d and 3d windows, * and rejects events if DataNode is not visible. * \return true if event is accepted, else false * * Overwrite this function to adapt for your own needs, for example to filter out events from * 3d windows like this: \code bool mitk::EventStateMachine::FilterEvents(InteractionEvent* interactionEvent, DataNode*dataNode) { return interactionEvent->GetSender()->GetMapperID() == BaseRenderer::Standard2D; // only 2D mappers } \endcode * or to enforce that the interactor only reacts when the corresponding DataNode is selected in the DataManager view.. */ virtual bool FilterEvents(InteractionEvent* interactionEvent, DataNode* dataNode); private: StateMachineContainer* m_StateMachineContainer; // storage of all states, action, transitions on which the statemachine operates. ActionFunctionsMapType m_ActionFunctionsMap; // stores association between action string StateMachineStateType m_CurrentState; }; } /* namespace mitk */ #endif /* MITKEVENTSTATEMACHINE_H_ */ diff --git a/Core/Code/Interactions/mitkGlobalInteraction.h b/Core/Code/Interactions/mitkGlobalInteraction.h index 973ebf51da..816a712f29 100755 --- a/Core/Code/Interactions/mitkGlobalInteraction.h +++ b/Core/Code/Interactions/mitkGlobalInteraction.h @@ -1,317 +1,323 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef GLOBALINTERACTION_H_HEADER_INCLUDED_C152938A #define GLOBALINTERACTION_H_HEADER_INCLUDED_C152938A #include "mitkFocusManager.h" #include #include "mitkStateMachineFactory.h" #include "mitkEventMapper.h" #include "mitkInteractor.h" namespace mitk { class PositionEvent; //##Documentation //## @brief handles all global Events //## //## superior statemachine, that spreads the events to all other interactors //## //## Initialization //## Attention: GlobalInteraction must be initialized by the Initialize() method //## before usage by giving it an XML scheme. Possibilities are giving it an empty string (default), //## the filename of an XML file or the actual XML content as std::string. If an empty string is given, //## the content is tried to be loaded from the default file location. //## //## Concept of sending events: //## In this concept of interaction, the statemachines can be divided into two main statemachines: //## Listeners and interactors. //## Listeners only receive the event to process it, but don't change any data. They want to listen to all events. //## Interactors do change data according to the received event. They do not need to receive all events, only //## those they are interested in. //## Additional to that a EVENT_NOTIFICATION_POLICY can be set. This can be either INFORM_MULTIPLE (the event is passed //## to all listeners) or INFORM_ONE (event is passed to the listener which can handle the event best and only to this one). //## //## To divide these two types of statemachine this class holds three lists and two maps: //## m_ListenerList, m_InteractorList, m_SelectedList and m_InteractorRelevanceMap and m_ListenerRelevanceMap //## The list m_ListenerList holds all listeners. //## m_InteractorList holds all interactors, and the List m_SelectedList holds all machines, that were set to SELECTED or SUBSELECTED. //## m_InteractorRelevanceMap and m_ListenerRelevanceMap map values returned from CanHandleEvent to the asked Interactors and Listeners. //## Through m_InteractorRelevanceMap stepping through interactors, that were not selected and could handle that event, can be done. //## Through m_ListenerRelevanceMap the listener which can handle the event best can be determined. In case of the INFORM_ONE notification policy //## the event is passed to just this listener //## //## First the listeners are informed with the event. //## Then the selected or subselected interactors are asked if they can handle that event. //## They can handle it, if the mode of the interactor after HandleEvent(..) is still in SMSELECTED or SMSUBSELECTED. //## They can't handle it, if the mode changed to SMDESELECTED. Then the interactor is removed from the selected-list. //## In that case, all interactors are asked to calculate and return their area of Relevance. //## An iterator is held on one interactor in the map. With the iterator, the map can be looped through so //## so that several geometric objects, that lie on top of each other, can be selected. //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} GlobalInteraction is deprecated. It is replaced by mitk::Dispatcher. + * Please use the new implementation described in \see DataInteractionPage . + */ + class MITK_CORE_EXPORT GlobalInteraction : public StateMachine { public: mitkClassMacro(GlobalInteraction, StateMachine); itkNewMacro(Self); typedef std::vector StateMachineList; typedef std::vector StateMachineCPointerList; typedef StateMachineList::iterator StateMachineListIter; typedef StateMachineCPointerList::iterator StateMachineCPointerListIter; typedef std::vector InteractorList; typedef InteractorList::iterator InteractorListIter; typedef std::multimap > InteractorMap; typedef std::multimap > StateMachineMap; typedef InteractorMap::iterator InteractorMapIter; typedef StateMachineMap::iterator StateMachineMapIter; /** * Enum for setting the event notification policy of the GlobalInteraction. */ enum EVENT_NOTIFICATION_POLICY { INFORM_MULTIPLE, /** For setting that all registered listeners are informed */ INFORM_ONE /** For setting that just the listener that can handle the event best is informed */ }; //##Documentation //## @brief add an Interactor to the list of all interactors that are asked for handling an event //## //## returns true in case of success void AddInteractor(Interactor* interactor); //##Documentation //## @brief remove a certain Interactor from the set of interactors that are asked for handling an event //## //## returns true in case of success bool RemoveInteractor(Interactor* interactor); //##Documentation //## @brief returns true, if the given interactor is already added to the Interactor-List bool InteractorRegistered (Interactor* interactor); //##Documentation //## @brief add a Listener to the list of all Listeners that are informed of an event //## //## returns true in case of success void AddListener(StateMachine* listener); //##Documentation //## @brief remove a certain Listener from the set of Listeners that are informed of an event //## //## returns true in case of success bool RemoveListener(StateMachine* listener); //##Documentation //## @brief returns true, if the given interactor is already added to the Listener-List bool ListenerRegistered (StateMachine* listener); //##Documentation //## @brief adds an element in the list in FocusManager //## //## true if success, false if the element is already in list bool AddFocusElement(FocusManager::FocusElement* element); //##Documentation //## @brief Removes an element in FocusManager //## //## true if success, false if the element was not in the list bool RemoveFocusElement(FocusManager::FocusElement* element); //##Documentation //## @brief Returns the focused Element in FocusManager FocusManager::FocusElement* GetFocus(); //##Documentation //## @brief Sets the given Element to focused //## //## returns true if the given element was found and focused bool SetFocus(FocusManager::FocusElement* element); //##Documentation //## @brief Returns the pointer to the FocusManager //## //## to add the observer for an event FocusManager* GetFocusManager(); //##Documentation //## @brief Returns the pointer to the EventMapper //## //## to add an addon EventMapper* GetEventMapper(); /** * @brief Return StateMachineFactory **/ StateMachineFactory* GetStateMachineFactory(); /** * @brief Returns the StartState of the StateMachine with the name type; * * Asks member StateMachineFactory for the StartState. * Returns NULL if no entry with name type is found. **/ State* GetStartState(const char* type); //##Documentation //## @brief Returns the global (singleton) instance of //## GlobalInteraction. Create it, if it does not exist. static GlobalInteraction* GetInstance(); //##Documentation //## @brief Initializes the global (singleton) instance of //## GlobalInteraction via an XML string. Must! be done before usage. Can be done only once. //## Can be used with an empty string (default), a file name with path, or the actual XML content as string. bool Initialize(const char* globalInteractionName, const std::string XMLBehaviorInput = ""); //##Documentation //## @brief Check if GlobalInteraction has already been initialized. Init must! be done before usage. bool IsInitialized() {return m_IsInitialized;} /** * @brief Set the policy of how the global interaction informs listeners and interactors * * INFORM_MULTIPLE broadcasts the event to all listeners and interactors that can handle the event * INFORM_ONE only informs the listener or interactor which can handle the event best **/ void SetEventNotificationPolicy(EVENT_NOTIFICATION_POLICY); /** * Return the current set eventspreading policy * @returns the current event spreading policy **/ EVENT_NOTIFICATION_POLICY GetEventNotificationPolicy() const; //so that the interactors can call AddToSelectedInteractors() and RemoveFromSelectedInteractors() friend class Interactor; protected: /** * @brief Default Constructor with type to load the StateMachinePattern of the StateMachine * @param XMLbehaviorFile the file which contains the statemachine and event patterns * @param type the name of the statemachine pattern this class shall use **/ GlobalInteraction(); /** * @brief Default destructor. **/ ~GlobalInteraction(); virtual bool ExecuteAction(Action* action, mitk::StateEvent const* stateEvent); /* *@brief adds the given interactor to the list of selected interactors. * This list is asked first to handle an event. */ virtual bool AddToSelectedInteractors(Interactor* interactor); /* *@brief removes the given interactor from the list of selected interactors * This list is asked first to handle an event. */ virtual bool RemoveFromSelectedInteractors(Interactor* interactor); private: //##Documentation //##@brief informing all statemachines that are held in the list m_ListenerList void InformListeners(mitk::StateEvent const* stateEvent); //##Documentation //##@brief asking the selected Interactor if an event can be handled //## //## returns false if no Interactor could handle the event bool AskSelected(mitk::StateEvent const* stateEvent); //##Documentation //##@brief asking next interactor of m_RelevanceMap bool AskCurrentInteractor(mitk::StateEvent const* stateEvent); //##Documentation //##@brief filling m_InteractorRelevanceMap //## //## @ params threshold: if the calculated Relevance value is above threshold, then add it to the map void FillInteractorRelevanceMap(mitk::StateEvent const* stateEvent, float threshold); //##Documentation //##@brief filling m_ListenerRelevanceMap //## //## @ params threshold: if the calculated Relevance value is above threshold, then add it to the map void FillListenerRelevanceMap(mitk::StateEvent const* stateEvent, float threshold); void RemoveFlaggedListeners(); StateMachineCPointerList m_ListenersFlaggedForRemoval; //##Documentation //## @brief list of all listening statemachines, that want to receive all events StateMachineList m_ListenerList; //##Documentation //## @brief list of all interactors (statemachine, that change data) InteractorList m_InteractorList; //##Documentation //## @brief list of all interactors, that are in Mode SELECTED or SUBSELECTED InteractorList m_SelectedList; //##Documentation //## @brief map for sorting all interactors by the value returned from CanHandleEvent(..). //## //## With that list certain interactors can be looped through like diving through layers InteractorMap m_InteractorRelevanceMap; //##Documentation //## @brief map for sorting all listeners by the value returned from CanHandleEvent(..). //## //## With that list certain listeners can be looped through like diving through layers StateMachineMap m_ListenerRelevanceMap; //##Documentation //## @brief iterator on an entry in m_RelevanceMap for stepping through interactors InteractorMapIter m_CurrentInteractorIter; //##Documentation //## @brief holds a list of BaseRenderer and one focused FocusManager::Pointer m_FocusManager; /** * @brief StatemachineFactory loads statemachine patterns and provides start states **/ StateMachineFactory* m_StateMachineFactory; /** * @brief EventMapper loads event patterns **/ EventMapper* m_EventMapper; bool m_CurrentlyInInformListenersLoop; bool m_CurrentlyInInformInteractorsLoop; bool m_IsInitialized; EVENT_NOTIFICATION_POLICY m_EventNotificationPolicy; }; } // namespace mitk #endif /* GLOBALINTERACTION_H_HEADER_INCLUDED_C152938A */ diff --git a/Core/Code/Interactions/mitkInformer.cpp b/Core/Code/Interactions/mitkInformer.cpp deleted file mode 100644 index dba4560923..0000000000 --- a/Core/Code/Interactions/mitkInformer.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/*=================================================================== - - The Medical Imaging Interaction Toolkit (MITK) - - Copyright (c) German Cancer Research Center, - Division of Medical and Biological Informatics. - All rights reserved. - - This software is distributed WITHOUT ANY WARRANTY; without - even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. - - See LICENSE.txt or http://www.mitk.org for details. - - ===================================================================*/ - -#include "mitkInformer.h" -#include -#include -#include - - - -mitk::InformerService::InformerService() -{ -} - -void mitk::InformerService::RegisterObserver(EventObserver* eventObserver) -{ - // explicitly use smart pointer, else the search for it will fail - // especially std::find() seems to fail on list of smart pointer objects - EventObserver::Pointer pEventObserver = eventObserver; - for (std::list::iterator it = m_ListObserver.begin(); it != m_ListObserver.end(); ++it) - { - if (*it == pEventObserver) - { - return; - } - } - m_ListObserver.push_back(pEventObserver); -} - -void mitk::InformerService::UnRegisterObserver(EventObserver* eventObserver) -{ - EventObserver::Pointer pEventObserver = eventObserver; - m_ListObserver.remove(pEventObserver); -} - -void mitk::InformerService::NotifyObservers(InteractionEvent::Pointer interactionEvent, bool isHandled) -{ - for (std::list::iterator it = m_ListObserver.begin(); it != m_ListObserver.end(); ++it) - { - (*it)->Notify(interactionEvent, isHandled); - } -} - -mitk::InformerService::~InformerService() -{ - m_ListObserver.clear(); -} diff --git a/Core/Code/Interactions/mitkInformer.h b/Core/Code/Interactions/mitkInformer.h deleted file mode 100644 index dd4a88ebc1..0000000000 --- a/Core/Code/Interactions/mitkInformer.h +++ /dev/null @@ -1,63 +0,0 @@ -/*=================================================================== - - The Medical Imaging Interaction Toolkit (MITK) - - Copyright (c) German Cancer Research Center, - Division of Medical and Biological Informatics. - All rights reserved. - - This software is distributed WITHOUT ANY WARRANTY; without - even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. - - See LICENSE.txt or http://www.mitk.org for details. - - ===================================================================*/ - -#ifndef mitkInformerService_h -#define mitkInformerService_h - -#include "mitkEventInformer.h" -#include "mitkInteractionEvent.h" -#include "mitkEventObserver.h" -#include "itkObject.h" -#include "itkObjectFactory.h" -#include -#include "mitkCommon.h" -#include -#include - -namespace mitk -{ - /** - * \class InformerService - * - * MicroService that handles informing the EventObservers about InteractionEvents. - * Also provides an interface to register and unregister EventObservers for InteractionEvents - */ - class MITK_CORE_EXPORT InformerService: public itk::Object - { - public: - /** - * \brief Register a new EventObserver - */ - void RegisterObserver(EventObserver* eventObserver); - /** - * \brief Unregister an EventObserver - */ - void UnRegisterObserver(EventObserver* eventObserver); - /** - * \brief Distributes an event to all registered observers - */ - void NotifyObservers(InteractionEvent::Pointer interactionEvent, bool isHandled); - - InformerService(); - ~InformerService(); - - private: - std::list m_ListObserver; // list that stores all registered observers - }; - -} /* namespace mitk */ -US_DECLARE_SERVICE_INTERFACE(mitk::InformerService, "org.mitk.InformerService") -#endif diff --git a/Core/Code/Interactions/mitkInteractionEvent.cpp b/Core/Code/Interactions/mitkInteractionEvent.cpp index d14abe307a..195e0f0c76 100644 --- a/Core/Code/Interactions/mitkInteractionEvent.cpp +++ b/Core/Code/Interactions/mitkInteractionEvent.cpp @@ -1,48 +1,53 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkException.h" #include "mitkInteractionEvent.h" mitk::InteractionEvent::InteractionEvent(BaseRenderer* baseRenderer, std::string eventClass) : m_Sender(baseRenderer) , m_EventClass(eventClass) { } void mitk::InteractionEvent::SetSender(mitk::BaseRenderer* sender) { m_Sender = sender; } mitk::BaseRenderer* mitk::InteractionEvent::GetSender() { - return m_Sender.GetPointer(); + return m_Sender; } bool mitk::InteractionEvent::MatchesTemplate(InteractionEvent::Pointer) { return false; } mitk::InteractionEvent::~InteractionEvent() { } -std::string mitk::InteractionEvent::GetEventClass() +bool mitk::InteractionEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} + +std::string mitk::InteractionEvent::GetEventClass() const { return m_EventClass; } diff --git a/Core/Code/Interactions/mitkInteractionEvent.h b/Core/Code/Interactions/mitkInteractionEvent.h index 5070b8d0cc..64ac405415 100644 --- a/Core/Code/Interactions/mitkInteractionEvent.h +++ b/Core/Code/Interactions/mitkInteractionEvent.h @@ -1,77 +1,75 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKINTERACTIONEVENT_H_ #define MITKINTERACTIONEVENT_H_ -#include "itkObject.h" +#include "itkLightObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkBaseRenderer.h" #include #include namespace mitk { - class MITK_CORE_EXPORT InteractionEvent: public itk::Object + class MITK_CORE_EXPORT InteractionEvent: public itk::LightObject { - public: - mitkClassMacro(InteractionEvent,itk::Object); - mitkNewMacro2Param(Self,BaseRenderer*, std::string); + mitkClassMacro(InteractionEvent,itk::LightObject) + mitkNewMacro2Param(Self,BaseRenderer*, std::string) + void SetSender(BaseRenderer* sender); BaseRenderer* GetSender(); /** * Implementation of equality for each event class. * Equality does \b not mean an exact copy or pointer equality. * * A match is determined by agreement in all attributes that are necessary to describe * the event for a state machine transition. * E.g. for a mouse event press event, it is important which modifiers are used, * which mouse button was used to triggered the event, but the mouse position is irrelevant. */ virtual bool MatchesTemplate(InteractionEvent::Pointer); /** * Return unique string identifier that gives the event class of this object, as it can be used in a state machine pattern. + * --- itk */ - std::string GetEventClass(); + std::string GetEventClass() const; + /** * This class implements an up cast to check if the provided baseClass object is derived from this class. * This function is used to support polymorphism on state machine pattern (XML) level. */ - template - bool IsSubClassOf(T *baseClass) - { - return dynamic_cast(baseClass) != NULL; - } + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: InteractionEvent(BaseRenderer*, std::string); virtual ~InteractionEvent(); private: - BaseRenderer::Pointer m_Sender; + BaseRenderer* m_Sender; std::string m_EventClass; }; } /* namespace mitk */ #endif /* MITKINTERACTIONEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkInteractionEventConst.h b/Core/Code/Interactions/mitkInteractionEventConst.h index 6c09341ab5..f332d73487 100644 --- a/Core/Code/Interactions/mitkInteractionEventConst.h +++ b/Core/Code/Interactions/mitkInteractionEventConst.h @@ -1,128 +1,131 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKINTERACTEVENTCONST_H #define MITKINTERACTEVENTCONST_H //##Documentation //## @file mitkInteractionEventConst.h //## @brief Constants to describe Mouse Events and special Key Events. +#include + namespace mitk { //##ButtonState // Mouse/keyboard state values enum MouseButtons { NoButton = 0x0000, LeftMouseButton = 0x0001, RightMouseButton = 0x0002, MiddleMouseButton = 0x0004, }; enum ModifierKeys { NoKey = 0x0000, ShiftKey = 0x0100, ControlKey = 0x0200, AltKey = 0x0400 }; /* * Allow bitwise OR operation on enums. */ inline MouseButtons operator|(MouseButtons a, MouseButtons b) { return static_cast(static_cast(a) | static_cast(b)); } - // TODO: FixME not working! - inline MouseButtons operator|=(MouseButtons a, MouseButtons b) + + inline MouseButtons& operator|=(MouseButtons& a, MouseButtons& b) { - return static_cast(static_cast(a) | static_cast(b)); + a = static_cast(static_cast(a) | static_cast(b)); + return a; } inline ModifierKeys operator|(ModifierKeys a, ModifierKeys b) { return static_cast(static_cast(a) | static_cast(b)); } -// TODO: FixME not working! - inline ModifierKeys operator|=(ModifierKeys a, ModifierKeys b) + inline ModifierKeys& operator|=(ModifierKeys& a, ModifierKeys& b) { - return static_cast(static_cast(a) | static_cast(b)); + a = static_cast(static_cast(a) | static_cast(b)); + return a; } /** * KeyConstants Constants for special keys */ // Special Keys const std::string KeyEsc = "Escape"; const std::string KeyEnter = "Enter"; const std::string KeyReturn = "Return"; const std::string KeyDelete = "Delete"; const std::string KeyArrowUp = "ArrowUp"; const std::string KeyArrowDown = "ArrowDown"; const std::string KeyArrowLeft = "ArrowLeft"; const std::string KeyArrowRight = "ArrowRight"; const std::string KeyF1 = "F1"; const std::string KeyF2 = "F2"; const std::string KeyF3 = "F3"; const std::string KeyF4 = "F4"; const std::string KeyF5 = "F5"; const std::string KeyF6 = "F6"; const std::string KeyF7 = "F7"; const std::string KeyF8 = "F8"; const std::string KeyF9 = "F9"; const std::string KeyF10 = "F10"; const std::string KeyF11 = "F11"; const std::string KeyF12 = "F12"; const std::string KeyPos1 = "Pos1"; const std::string KeyEend = "End"; const std::string KeyInsert = "Insert"; const std::string KeyPageUp = "PageUp"; const std::string KeyPageDown = "PageDown"; // End special keys // XML Tags const std::string xmlTagConfigRoot = "config"; const std::string xmlTagParam = "param"; - const std::string xmlTagInput = "input"; + const std::string xmlTagEventVariant = "event_variant"; const std::string xmlTagAttribute = "attribute"; // XML Param const std::string xmlParameterName = "name"; const std::string xmlParameterValue = "value"; const std::string xmlParameterEventVariant = "event_variant"; - const std::string xmlParameterEventClass = "event_class"; + const std::string xmlParameterEventClass = "class"; // Event Description const std::string xmlEventPropertyModifier = "Modifiers"; const std::string xmlEventPropertyEventButton = "EventButton"; const std::string xmlEventPropertyButtonState = "ButtonState"; const std::string xmlEventPropertyKey = "Key"; const std::string xmlEventPropertyScrollDirection = "ScrollDirection"; const std::string xmlEventPropertySignalName = "SignalName"; // Predefined internal events/signals const std::string IntDeactivateMe = "DeactivateMe"; const std::string IntLeaveWidget = "LeaveWidget"; const std::string IntEnterWidget = "EnterWidget"; } //namespace mitk #endif //ifndef MITKINTERACTEVENTCONST_H diff --git a/Core/Code/Interactions/mitkEventHandler.cpp b/Core/Code/Interactions/mitkInteractionEventHandler.cpp similarity index 66% rename from Core/Code/Interactions/mitkEventHandler.cpp rename to Core/Code/Interactions/mitkInteractionEventHandler.cpp index 7cb125615e..2157bf592e 100644 --- a/Core/Code/Interactions/mitkEventHandler.cpp +++ b/Core/Code/Interactions/mitkInteractionEventHandler.cpp @@ -1,75 +1,75 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkEventHandler.h" +#include "mitkInteractionEventHandler.h" #include "mitkInteractionEvent.h" -mitk::EventHandler::EventHandler(): +mitk::InteractionEventHandler::InteractionEventHandler(): m_EventConfig(NULL) { } -mitk::EventHandler::~EventHandler() +mitk::InteractionEventHandler::~InteractionEventHandler() { } -bool mitk::EventHandler::LoadEventConfig(std::string filename, std::string moduleName) +bool mitk::InteractionEventHandler::LoadEventConfig(std::string filename, std::string moduleName) { m_EventConfig = vtkSmartPointer::New(); // notify sub-classes that new config is set bool success = m_EventConfig->LoadConfig(filename, moduleName); ConfigurationChanged(); return success; } -bool mitk::EventHandler::AddEventConfig(std::string filename, std::string moduleName) +bool mitk::InteractionEventHandler::AddEventConfig(std::string filename, std::string moduleName) { if (m_EventConfig == NULL) { MITK_ERROR<< "LoadEventConfig has to be called before AddEventConfig can be used."; return false; } // notify sub-classes that new config is set bool success = m_EventConfig->LoadConfig(filename, moduleName); ConfigurationChanged(); return success; } -mitk::PropertyList::Pointer mitk::EventHandler::GetAttributes() +mitk::PropertyList::Pointer mitk::InteractionEventHandler::GetAttributes() { if (m_EventConfig != NULL) { return m_EventConfig->GetAttributes(); } else { - MITK_ERROR << "EventHandler::GetAttributes() requested, but not configuration loaded."; + MITK_ERROR << "InteractionEventHandler::GetAttributes() requested, but not configuration loaded."; return NULL; } } -std::string mitk::EventHandler::MapToEventVariant(InteractionEvent* interactionEvent) +std::string mitk::InteractionEventHandler::MapToEventVariant(InteractionEvent* interactionEvent) { if (m_EventConfig != NULL) { return m_EventConfig->GetMappedEvent(interactionEvent); } else { return ""; } } -void mitk::EventHandler::ConfigurationChanged() +void mitk::InteractionEventHandler::ConfigurationChanged() { } diff --git a/Core/Code/Interactions/mitkEventHandler.h b/Core/Code/Interactions/mitkInteractionEventHandler.h similarity index 82% rename from Core/Code/Interactions/mitkEventHandler.h rename to Core/Code/Interactions/mitkInteractionEventHandler.h index f376ccf09a..8b45862464 100644 --- a/Core/Code/Interactions/mitkEventHandler.h +++ b/Core/Code/Interactions/mitkInteractionEventHandler.h @@ -1,83 +1,84 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKEVENTHANDLER_H_ #define MITKEVENTHANDLER_H_ -#include "itkObject.h" +#include "itkLightObject.h" #include "itkObjectFactory.h" #include "mitkEvent.h" #include "mitkCommon.h" #include #include "mitkEventConfig.h" #include "mitkPropertyList.h" #include #include namespace mitk { /** * \class EventHandler - * Base Class for Interaction handling classes. - * Handles loading of configuration object and mapping of events to variant names. + * Serves as a base class for all objects and classes that handle mitk::InteractionEvents. + * + * It provides an interface to load configuration objects map of events to variant names. */ class InteractionEvent; - class MITK_CORE_EXPORT EventHandler : public itk::Object { + class MITK_CORE_EXPORT InteractionEventHandler : public itk::LightObject { public: - mitkClassMacro(EventHandler, itk::Object); - itkNewMacro(Self); + mitkClassMacro(InteractionEventHandler, itk::LightObject) + itkNewMacro(Self) /** * @brief Loads XML resource * * Loads a XML resource file in the given module context. * Default is the Mitk module (core). * The files have to be placed in the Resources/Interaction folder of their respective module. * This method will remove all existing configuration and replaces it with the new one. */ virtual bool LoadEventConfig(std::string filename, std::string moduleName = "Mitk"); /** * This method EXTENDs the configuration. * The configuration from the resource provided is loaded and only the ones conflicting are replaced by the new one. * This way several configuration files can be combined */ virtual bool AddEventConfig(std::string filename, std::string moduleName = "Mitk"); protected: - EventHandler(); - virtual ~EventHandler(); + InteractionEventHandler(); + virtual ~InteractionEventHandler(); /** * Returns a PropertyList in which the parameters defined in the config file are listed. */ PropertyList::Pointer GetAttributes(); std::string MapToEventVariant(InteractionEvent* interactionEvent); /** * Is called whenever a new config object ist set. * Overwrite this method e.g. to initialize EventHandler with parameters in configuration file. */ virtual void ConfigurationChanged(); private: vtkSmartPointer m_EventConfig; }; } /* namespace mitk */ #endif /* MITKEVENTHANDLER_H_ */ diff --git a/Core/Code/Interactions/mitkInteractionKeyEvent.cpp b/Core/Code/Interactions/mitkInteractionKeyEvent.cpp index c2dd7792fb..feb979df3f 100644 --- a/Core/Code/Interactions/mitkInteractionKeyEvent.cpp +++ b/Core/Code/Interactions/mitkInteractionKeyEvent.cpp @@ -1,47 +1,52 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkInteractionKeyEvent.h" -mitk::InteractionKeyEvent::InteractionKeyEvent(mitk::BaseRenderer* baseRenderer, std::string key, mitk::ModifierKeys modifiers = ControlKey) : +mitk::InteractionKeyEvent::InteractionKeyEvent(mitk::BaseRenderer* baseRenderer, const std::string key, mitk::ModifierKeys modifiers = ControlKey) : InteractionEvent(baseRenderer, "KeyEvent"), m_Key(key), m_Modifiers(modifiers) { } mitk::ModifierKeys mitk::InteractionKeyEvent::GetModifiers() const { return m_Modifiers; } std::string mitk::InteractionKeyEvent::GetKey() const { return m_Key; } mitk::InteractionKeyEvent::~InteractionKeyEvent() { } bool mitk::InteractionKeyEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { mitk::InteractionKeyEvent* keyEvent = dynamic_cast(interactionEvent.GetPointer()); if (keyEvent == NULL) { return false; } return (this->GetModifiers() == keyEvent->GetModifiers() && this->GetKey() == keyEvent->GetKey()); } + +bool mitk::InteractionKeyEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkInteractionKeyEvent.h b/Core/Code/Interactions/mitkInteractionKeyEvent.h index c0bfc924c4..7dea3c994c 100644 --- a/Core/Code/Interactions/mitkInteractionKeyEvent.h +++ b/Core/Code/Interactions/mitkInteractionKeyEvent.h @@ -1,64 +1,65 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKINTERACTIONKEYEVENT_H_ #define MITKINTERACTIONKEYEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEventConst.h" #include "mitkInteractionPositionEvent.h" #include "mitkBaseRenderer.h" #include "mitkInteractionEvent.h" #include #include /* * Note: A Click with the MiddleButton is to be handled with MousePressEvents */ namespace mitk { /** * \class InteractionKeyEvent * \brief Handles key events. * \input std::string for pressed key or special key description , mitk::ModifierKeys for modifiers * \ingroup Interaction. */ class MITK_CORE_EXPORT InteractionKeyEvent : public InteractionEvent { public: - mitkClassMacro(InteractionKeyEvent,InteractionEvent); - mitkNewMacro3Param(Self, BaseRenderer*, std::string , ModifierKeys); + mitkClassMacro(InteractionKeyEvent,InteractionEvent) + mitkNewMacro3Param(Self, BaseRenderer*, const std::string , ModifierKeys) virtual bool MatchesTemplate(InteractionEvent::Pointer); + bool IsSuperClassOf(InteractionEvent::Pointer baseClass); ModifierKeys GetModifiers() const; std::string GetKey() const; protected: - InteractionKeyEvent(BaseRenderer*, std::string key, ModifierKeys modifiers); + InteractionKeyEvent(BaseRenderer*, const std::string key, ModifierKeys modifiers); virtual ~InteractionKeyEvent(); private: std::string m_Key; ModifierKeys m_Modifiers; }; } /* namespace mitk */ #endif /* MITKINTERACTIONKEYEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkInteractionPositionEvent.cpp b/Core/Code/Interactions/mitkInteractionPositionEvent.cpp index 42cecbcffb..155f6c80a0 100644 --- a/Core/Code/Interactions/mitkInteractionPositionEvent.cpp +++ b/Core/Code/Interactions/mitkInteractionPositionEvent.cpp @@ -1,53 +1,58 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkInteractionPositionEvent.h" #include mitk::InteractionPositionEvent::InteractionPositionEvent(mitk::BaseRenderer* baseRenderer, - mitk::Point2D mousePosition, - std::string eventClass) + const mitk::Point2D mousePosition, + const std::string eventClass) : InteractionEvent(baseRenderer, eventClass) , m_PointerPosition(mousePosition) { if (GetSender() != NULL) { m_WorldPosition = GetSender()->Map2DRendererPositionTo3DWorldPosition(&m_PointerPosition); } else { m_WorldPosition.Fill(0); } } -mitk::Point2D mitk::InteractionPositionEvent::GetPointerPositionOnScreen() +const mitk::Point2D mitk::InteractionPositionEvent::GetPointerPositionOnScreen() { return m_PointerPosition; } -mitk::Point3D mitk::InteractionPositionEvent::GetPositionInWorld() +const mitk::Point3D mitk::InteractionPositionEvent::GetPositionInWorld() { return m_WorldPosition; } bool mitk::InteractionPositionEvent::MatchesTemplate(InteractionEvent::Pointer) { return true; } mitk::InteractionPositionEvent::~InteractionPositionEvent() { } + +bool mitk::InteractionPositionEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkInteractionPositionEvent.h b/Core/Code/Interactions/mitkInteractionPositionEvent.h index b7d43a8328..5f7960cd9a 100644 --- a/Core/Code/Interactions/mitkInteractionPositionEvent.h +++ b/Core/Code/Interactions/mitkInteractionPositionEvent.h @@ -1,63 +1,65 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKINTERACTIONPOSITIONEVENT_H_ #define MITKINTERACTIONPOSITIONEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEvent.h" #include "mitkInteractionEventConst.h" #include #include namespace mitk { /** * \class InteractionPositionEvent * * \brief Super class for all position events. * * This class is instantiated with a BaseRenderer and the 2D pointer position relative to the renderer, * the object then queries the Renderer for 3D world coordinates and supplies them to deriving classes. * */ class MITK_CORE_EXPORT InteractionPositionEvent : public InteractionEvent { public: mitkClassMacro(InteractionPositionEvent,InteractionEvent); - mitkNewMacro3Param(Self, BaseRenderer*, Point2D , std::string); + mitkNewMacro3Param(Self, BaseRenderer*, const Point2D , const std::string); - Point2D GetPointerPositionOnScreen(); - Point3D GetPositionInWorld(); + const Point2D GetPointerPositionOnScreen(); + const Point3D GetPositionInWorld(); - protected: - InteractionPositionEvent(BaseRenderer* baseRenderer, Point2D mousePosition, std::string eventClass); virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); + + protected: + InteractionPositionEvent(BaseRenderer* baseRenderer, const Point2D mousePosition, const std::string eventClass); virtual ~InteractionPositionEvent(); private: Point2D m_PointerPosition; Point3D m_WorldPosition; }; } /* namespace mitk */ #endif /* MITKINTERACTIONPOSITIONEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkInteractor.h b/Core/Code/Interactions/mitkInteractor.h index 1178a06d81..8574a27b4f 100755 --- a/Core/Code/Interactions/mitkInteractor.h +++ b/Core/Code/Interactions/mitkInteractor.h @@ -1,170 +1,174 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef INTERACTOR_H_HEADER_INCLUDED #define INTERACTOR_H_HEADER_INCLUDED #include #include "mitkStateMachine.h" #include "mitkGeometry3D.h" #include namespace mitk { class DataNode; class BaseData; //##Documentation //## @brief Interface for an Interactor. //## //## The Interactor is held with a SmartPointer by a DataNode //## and holds its Node with a Pointer. That way Smartpointer doesn't build a circle. //## Different Modes: In order to not send Events to all StateMachines, a StateMachine can be //## in three different modes: //## DESELECTED: this statemachine doesn't wait for an event //## SELECTED: this statemachine just has handled an event and waits for the next one //## SUBSELECTED: depricate; was used for hierarchical statemachines before. //## Guidelines for the modevalues: Selected if the coresponding data is selected, deselected if deselect of data. //## //## In moving the machine is selected. After a new insert the machine is selected, since the data is also selected //## In method ExecuteAction(..) the different actions are divided up through switch/case statements. Each block has to check //## the appropriate type of event to process the actions. Especially in guarding states (a state, that checks certain conditions (e.g. is picked) //## the according Event must be called to continue in states. No return false here! //## @ingroup Interaction +/** + * \deprecatedSince{2013_03} mitk::Interactor is deprecated. Use mitk::DataInteractor instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ class MITK_CORE_EXPORT Interactor : public StateMachine { public: mitkClassMacro(Interactor, StateMachine); /** * @brief NewMacro with two parameters for calling itk::Lightobject::New(..) method **/ mitkNewMacro2Param(Self, const char*, DataNode*); //##Documentation //##@brief Enumeration of the different modes an Interactor can be into. //## See class documentation for further details enum SMMode { SMDESELECTED = 0, SMSELECTED, SMSUBSELECTED }; typedef SMMode ModeType; //##Documentation //## @brief Get the Mode of the Interactor. Use enum SMMode for return parameter SMMode GetMode() const; //##Documentation //## @brief Check the interaction mode bool IsNotSelected() const; //##Documentation //## @brief Check the interaction mode bool IsSelected() const; //##Documentation //## @brief calculates how good the data, this statemachine handles, is hit by the event. //## //## Returns a value between 0 and 1 //## where 0 represents not responsible and 1 represents definitive responsible! //## Standard function to override if needed. //## (Used by GlobalInteraction to decide which DESELECTED statemachine to send the event to.) virtual float CanHandleEvent(StateEvent const* stateEvent) const; /** * @brief Updates the current TimeStep according to the associated data and calls Superclass::HandleEvent() **/ bool HandleEvent(StateEvent const* stateEvent); /** * @brief Method to call if the associated data has changed by the user (loading of data) * This method is called by DataNode::SetData() to tell the interactor to reinitialize. * This method should be overwritten by specialized interactors. * (e.g. PointSetInteractor: go to the right state according to number of loaded points) * Note: It will not be called when the data gets modified (e.g. adding / removing points to a PointSet) **/ virtual void DataChanged(){}; //##Documentation //## @brief adds handling of operations used for mode change. Unrecognized Operations are send to Superclass. //## *ATTENTION*: THIS METHOD SHOULD NOT BE CALLED FROM OTHER CLASSES DIRECTLY! virtual void ExecuteOperation(Operation* operation); static const std::string XML_NODE_NAME; protected: /** * @brief Constructor * @param dataNode is the node, this Interactor is connected to * @param type is the type of StateMachine like declared in the XML-Configure-File * * Interactor connects itself to the DataNode-Interactor-pointer through call of SetInteractor(this) **/ Interactor(const char * type, DataNode* dataNode); /** * @brief Destructor **/ ~Interactor(){} bool OnModeSelect(Action* action, StateEvent const*); bool OnModeDeselect(Action* action, StateEvent const*); bool OnModeSubSelect(Action* action, StateEvent const*); //##Documentation virtual const std::string& GetXMLNodeName() const; //##Documentation //## @brief creates a ModeOperation with the transmitted mode and sends it to this. Undo supported! void CreateModeOperation(ModeType mode); //##Documentation //## @brief convenience method for accessing the data contained in the //## node to which this interactor is associated to BaseData* GetData() const; //##Documentation //## @brief Used by friend class DataNode virtual void SetDataNode( DataNode* dataNode ); /** * @brief Derived from superclass to also check if enough timesteps are instantiated in m_CurrentStateVector * The number of timesteps is read from the dedicated data. * @param[in] timeStep The timeStep that the statemachine has to be set to **/ virtual void UpdateTimeStep(unsigned int timeStep); //##Documentation //## @brief Pointer to the data, this object handles the Interaction for DataNode* m_DataNode; //##Documentation //## @brief Mode of Selection ModeType m_Mode; friend class DataNode; }; }//namespace mitk #endif /* INTERACTOR_H_HEADER_INCLUDED */ diff --git a/Core/Code/Interactions/mitkInternalEvent.cpp b/Core/Code/Interactions/mitkInternalEvent.cpp index e9950f6a35..15622e6bc1 100644 --- a/Core/Code/Interactions/mitkInternalEvent.cpp +++ b/Core/Code/Interactions/mitkInternalEvent.cpp @@ -1,50 +1,55 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkInternalEvent.h" #include "mitkDataInteractor.h" -mitk::InternalEvent::InternalEvent(mitk::BaseRenderer* baseRenderer, DataInteractor* sourceInteractor, std::string signalName) +mitk::InternalEvent::InternalEvent(mitk::BaseRenderer* baseRenderer, DataInteractor* sourceInteractor, const std::string signalName) : InteractionEvent(baseRenderer, "InternalEvent") , m_DataInteractor(sourceInteractor) , m_SignalName(signalName) { } bool mitk::InternalEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { mitk::InternalEvent* internalEvent = dynamic_cast(interactionEvent.GetPointer()); if (internalEvent == NULL) { return false; } return (m_SignalName == internalEvent->GetSignalName()); } mitk::InternalEvent::~InternalEvent() { } -std::string mitk::InternalEvent::GetSignalName() +const std::string mitk::InternalEvent::GetSignalName() { return m_SignalName; } mitk::DataInteractor* mitk::InternalEvent::GetTargetInteractor() { return m_DataInteractor.GetPointer(); } + +bool mitk::InternalEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (NULL != dynamic_cast(baseClass.GetPointer()) ); +} diff --git a/Core/Code/Interactions/mitkInternalEvent.h b/Core/Code/Interactions/mitkInternalEvent.h index 468eb26b9d..4d511084e2 100644 --- a/Core/Code/Interactions/mitkInternalEvent.h +++ b/Core/Code/Interactions/mitkInternalEvent.h @@ -1,62 +1,63 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkInternalEvent_h #define mitkInternalEvent_h #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEventConst.h" #include "mitkInteractionEvent.h" #include "mitkBaseRenderer.h" #include #include namespace mitk { /** *\brief Class to create events from within the application to signal about internal events. * * These events can target a specific DataInteractor, if this DataInteractor is specified in the constructor; * else this parameter is set to NULL and the event is treated as a regular event. */ class DataInteracor; class MITK_CORE_EXPORT InternalEvent: public InteractionEvent { public: mitkClassMacro(InternalEvent,InteractionEvent); - mitkNewMacro3Param(Self, BaseRenderer*, DataInteractor*, std::string); + mitkNewMacro3Param(Self, BaseRenderer*, DataInteractor*, const std::string); - std::string GetSignalName(); + const std::string GetSignalName(); DataInteractor* GetTargetInteractor(); virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: - InternalEvent(BaseRenderer*, DataInteractor* destInteractor, std::string signalName); + InternalEvent(BaseRenderer*, DataInteractor* destInteractor, const std::string signalName); virtual ~InternalEvent(); private: DataInteractor::Pointer m_DataInteractor; std::string m_SignalName; }; } #endif /* mitkInternalEvent_h */ diff --git a/Core/Code/Interactions/mitkKeyEvent.h b/Core/Code/Interactions/mitkKeyEvent.h index 080d0e429b..6f4f555edb 100644 --- a/Core/Code/Interactions/mitkKeyEvent.h +++ b/Core/Code/Interactions/mitkKeyEvent.h @@ -1,78 +1,83 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef KeyEvent_H_HEADER_INCLUDED_C184F366 #define KeyEvent_H_HEADER_INCLUDED_C184F366 #include #include "mitkEvent.h" #include "mitkVector.h" namespace mitk { //##Documentation //## @brief Event that stores coordinates and the key which is pressed //## //## Stores display position of the mouse. If requested, the correspondent //## 3D world position in mm is calculated via picking (delegated to the //## BaseRenderer). //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} KeyEvent is deprecated. Use mitk::InteractionKeyEvent instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ class MITK_CORE_EXPORT KeyEvent : public Event { public: //##Documentation //## @brief Constructor with all necessary arguments. //## //## @param sender is the renderer that caused that event //## @param type, button, buttonState, key: information from the Event //## @param displPosition is the 2D Position of the mouse KeyEvent(BaseRenderer* sender, int type, int button, int buttonState, int key, std::string text, const Point2D& displPosition); const Point2D& GetDisplayPosition() const { return m_DisplayPosition; } void SetDisplayPosition(const Point2D& displPosition) { m_DisplayPosition = displPosition; } const Point3D& GetWorldPosition() const; int GetKey() const { return m_Key; } const char* GetText() const { return m_Text.c_str(); } int GetType() const { return m_Type; } protected: Point2D m_DisplayPosition; int m_Key; std::string m_Text; mutable Point3D m_WorldPosition; mutable bool m_WorldPositionIsSet; }; } // namespace mitk #endif /* DISPLAYPOSITIONozsiEVENT_H_HEADER_INCLUDED_C184F366 */ diff --git a/Core/Code/Interactions/mitkMouseModeSwitcher.cpp b/Core/Code/Interactions/mitkMouseModeSwitcher.cpp index 43955309d9..2c8169dfb4 100644 --- a/Core/Code/Interactions/mitkMouseModeSwitcher.cpp +++ b/Core/Code/Interactions/mitkMouseModeSwitcher.cpp @@ -1,112 +1,110 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkMouseModeSwitcher.h" // us #include "mitkGetModuleContext.h" #include "mitkModule.h" #include "mitkModuleRegistry.h" -#include "mitkInformer.h" +#include "mitkInteractionEventObserver.h" mitk::MouseModeSwitcher::MouseModeSwitcher() : - m_ActiveInteractionScheme(MITK), m_ActiveMouseMode(MousePointer) + m_ActiveInteractionScheme(MITK), m_ActiveMouseMode(MousePointer), m_CurrentObserver(NULL) { - m_CurrentObserver = NULL; this->InitializeListeners(); this->SetInteractionScheme(m_ActiveInteractionScheme); } mitk::MouseModeSwitcher::~MouseModeSwitcher() { + m_ServiceRegistration.Unregister(); } void mitk::MouseModeSwitcher::InitializeListeners() { if (m_CurrentObserver.IsNull()) { m_CurrentObserver = mitk::DisplayInteractor::New(); m_CurrentObserver->LoadStateMachine("DisplayInteraction.xml"); m_CurrentObserver->LoadEventConfig("DisplayConfigMITK.xml"); - // Register as listener - mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); - mitk::ServiceReference serviceRef = context->GetServiceReference(); - mitk::InformerService* service = dynamic_cast(context->GetService(serviceRef)); - service->RegisterObserver(m_CurrentObserver.GetPointer()); + // Register as listener via micro services + m_ServiceRegistration = GetModuleContext()->RegisterService( + m_CurrentObserver.GetPointer()); } } void mitk::MouseModeSwitcher::SetInteractionScheme(InteractionScheme scheme) { switch (scheme) { case MITK: { m_CurrentObserver->LoadEventConfig("DisplayConfigMITK.xml"); } break; case PACS: { m_CurrentObserver->LoadEventConfig("DisplayConfigPACS.xml"); } break; } m_ActiveInteractionScheme = scheme; - this->InvokeEvent( MouseModeChangedEvent() ); + this->InvokeEvent(MouseModeChangedEvent()); } void mitk::MouseModeSwitcher::SelectMouseMode(MouseMode mode) { if (m_ActiveInteractionScheme != PACS) return; switch (mode) { case MousePointer: { m_CurrentObserver->LoadEventConfig("DisplayConfigPACS.xml"); break; } // case 0 case Scroll: { m_CurrentObserver->AddEventConfig("DisplayConfigPACSScroll.xml"); break; } case LevelWindow: { m_CurrentObserver->AddEventConfig("DisplayConfigPACSLevelWindow.xml"); break; } case Zoom: { m_CurrentObserver->AddEventConfig("DisplayConfigPACSZoom.xml"); break; } case Pan: { m_CurrentObserver->AddEventConfig("DisplayConfigPACSPan.xml"); break; } } // end switch (mode) m_ActiveMouseMode = mode; - this->InvokeEvent( MouseModeChangedEvent() ); + this->InvokeEvent(MouseModeChangedEvent()); } mitk::MouseModeSwitcher::MouseMode mitk::MouseModeSwitcher::GetCurrentMouseMode() const { return m_ActiveMouseMode; } diff --git a/Core/Code/Interactions/mitkMouseModeSwitcher.h b/Core/Code/Interactions/mitkMouseModeSwitcher.h index 4d9347bcc8..c3d54cf19b 100644 --- a/Core/Code/Interactions/mitkMouseModeSwitcher.h +++ b/Core/Code/Interactions/mitkMouseModeSwitcher.h @@ -1,124 +1,129 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKMouseModeSwitcher_H_HEADER_INCLUDED_C10DC4EB #define MITKMouseModeSwitcher_H_HEADER_INCLUDED_C10DC4EB #include "MitkExports.h" #include #include "mitkDisplayInteractor.h" namespace mitk { /*********************************************************************** * * \brief Class that offers a convenient way to switch between different * interaction schemes * * This class offers the possibility to switch between the two different * interaction schemes that are available: * - MITK : The original interaction scheme * - left mouse button : setting the cross position in the MPR view * - middle mouse button : panning * - right mouse button : zooming * * * - PACS : an alternative interaction scheme that behaves more like a * PACS workstation * - left mouse button : behavior depends on current MouseMode * - middle mouse button : fast scrolling * - right mouse button : level-window * - ctrl + right button : zooming * - shift+ right button : panning * * There are 5 different MouseModes that are available in the PACS scheme. * Each MouseMode defines the interaction that is performed on a left * mouse button click: * - Pointer : sets the cross position for the MPR * - Scroll * - Level-Window * - Zoom * - Pan * * When the interaction scheme or the MouseMode is changed, this class * manages the adding and removing of the relevant listeners offering * a convenient way to modify the interaction behavior. * ***********************************************************************/ class MITK_CORE_EXPORT MouseModeSwitcher : public itk::Object { public: #pragma GCC visibility push(default) /** \brief Can be observed by GUI class to update button states when mode is changed programatically. */ itkEventMacro( MouseModeChangedEvent, itk::AnyEvent ); #pragma GCC visibility pop mitkClassMacro( MouseModeSwitcher, itk::Object ); itkNewMacro(Self); // enum of the different interaction schemes that are available enum InteractionScheme { PACS = 0, MITK = 1 }; // enum of available mouse modes for PACS interaction scheme enum MouseMode { MousePointer = 0, Scroll, LevelWindow, Zoom, Pan }; /** * \brief Setter for interaction scheme */ void SetInteractionScheme( InteractionScheme ); /** * \brief Setter for mouse mode */ void SelectMouseMode( MouseMode mode ); /** * \brief Returns the current mouse mode */ MouseMode GetCurrentMouseMode() const; protected: MouseModeSwitcher(); virtual ~MouseModeSwitcher(); private: /** * \brief Initializes the listener with the MITK default behavior. */ void InitializeListeners(); InteractionScheme m_ActiveInteractionScheme; MouseMode m_ActiveMouseMode; DisplayInteractor::Pointer m_CurrentObserver; + /** + * Reference to the service registration of the observer, + * it is needed to unregister the observer on unload. + */ + ServiceRegistration m_ServiceRegistration; }; } // namespace mitk #endif /* MITKMouseModeSwitcher_H_HEADER_INCLUDED_C10DC4EB */ diff --git a/Core/Code/Interactions/mitkMouseMoveEvent.cpp b/Core/Code/Interactions/mitkMouseMoveEvent.cpp index 7184da4a05..31492997e0 100644 --- a/Core/Code/Interactions/mitkMouseMoveEvent.cpp +++ b/Core/Code/Interactions/mitkMouseMoveEvent.cpp @@ -1,60 +1,64 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkException.h" #include "mitkMouseMoveEvent.h" -mitk::MouseMoveEvent::MouseMoveEvent(mitk::BaseRenderer* baseRenderer, mitk::Point2D mousePosition = NULL, mitk::MouseButtons buttonStates = - NoButton, mitk::ModifierKeys modifiers = NoKey) +mitk::MouseMoveEvent::MouseMoveEvent(mitk::BaseRenderer* baseRenderer, mitk::Point2D mousePosition , mitk::MouseButtons buttonStates, mitk::ModifierKeys modifiers) : InteractionPositionEvent(baseRenderer, mousePosition, "MouseMoveEvent") , m_ButtonStates(buttonStates) , m_Modifiers(modifiers) { } mitk::ModifierKeys mitk::MouseMoveEvent::GetModifiers() const { return m_Modifiers; } mitk::MouseButtons mitk::MouseMoveEvent::GetButtonStates() const { return m_ButtonStates; } void mitk::MouseMoveEvent::SetModifiers(ModifierKeys modifiers) { m_Modifiers = modifiers; } void mitk::MouseMoveEvent::SetButtonStates(MouseButtons buttons) { m_ButtonStates = buttons; } mitk::MouseMoveEvent::~MouseMoveEvent() { } bool mitk::MouseMoveEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { mitk::MouseMoveEvent* mpe = dynamic_cast(interactionEvent.GetPointer()); if (mpe == NULL) { return false; } return (this->GetModifiers() == mpe->GetModifiers() && this->GetButtonStates() == mpe->GetButtonStates()); } + +bool mitk::MouseMoveEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkMouseMoveEvent.h b/Core/Code/Interactions/mitkMouseMoveEvent.h index db1bc60dbe..dc7dd8a5cf 100644 --- a/Core/Code/Interactions/mitkMouseMoveEvent.h +++ b/Core/Code/Interactions/mitkMouseMoveEvent.h @@ -1,56 +1,57 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKMOUSEMOVEEVENT_H_ #define MITKMOUSEMOVEEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEventConst.h" #include "mitkInteractionPositionEvent.h" #include "mitkBaseRenderer.h" #include "mitkInteractionEvent.h" #include namespace mitk { class MITK_CORE_EXPORT MouseMoveEvent : public InteractionPositionEvent { public: mitkClassMacro(MouseMoveEvent,InteractionPositionEvent); mitkNewMacro4Param(Self, BaseRenderer*, Point2D , MouseButtons , ModifierKeys); ModifierKeys GetModifiers() const; MouseButtons GetButtonStates() const; void SetModifiers(ModifierKeys modifiers); void SetButtonStates(MouseButtons buttons); virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: - MouseMoveEvent(BaseRenderer*, Point2D, MouseButtons buttonStates, ModifierKeys modifiers); + MouseMoveEvent(BaseRenderer*, Point2D = Point2D(), MouseButtons buttonStates = NoButton, mitk::ModifierKeys modifiers = NoKey); virtual ~MouseMoveEvent(); private: MouseButtons m_ButtonStates; ModifierKeys m_Modifiers; }; } /* namespace mitk */ #endif /* MITKMOUSEMOVEEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkMousePressEvent.cpp b/Core/Code/Interactions/mitkMousePressEvent.cpp index e8fdff0887..6026811db7 100644 --- a/Core/Code/Interactions/mitkMousePressEvent.cpp +++ b/Core/Code/Interactions/mitkMousePressEvent.cpp @@ -1,75 +1,80 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkException.h" #include "mitkMousePressEvent.h" mitk::MousePressEvent::MousePressEvent(mitk::BaseRenderer* baseRenderer, - mitk::Point2D mousePosition, + const mitk::Point2D mousePosition, mitk::MouseButtons buttonStates, mitk::ModifierKeys modifiers, mitk::MouseButtons eventButton) : InteractionPositionEvent(baseRenderer, mousePosition, "MousePressEvent") , m_EventButton(eventButton) , m_ButtonStates(buttonStates) , m_Modifiers( modifiers) { } mitk::MouseButtons mitk::MousePressEvent::GetEventButton() const { return m_EventButton; } void mitk::MousePressEvent::SetEventButton(MouseButtons buttons) { m_EventButton = buttons; } mitk::ModifierKeys mitk::MousePressEvent::GetModifiers() const { return m_Modifiers; } mitk::MouseButtons mitk::MousePressEvent::GetButtonStates() const { return m_ButtonStates; } void mitk::MousePressEvent::SetModifiers(ModifierKeys modifiers) { m_Modifiers = modifiers; } void mitk::MousePressEvent::SetButtonStates(MouseButtons buttons) { m_ButtonStates = buttons; } mitk::MousePressEvent::~MousePressEvent() { } bool mitk::MousePressEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { mitk::MousePressEvent* mpe = dynamic_cast(interactionEvent.GetPointer()); if (mpe == NULL) { return false; } return (this->GetEventButton() == mpe->GetEventButton() && this->GetModifiers() == mpe->GetModifiers() && this->GetButtonStates() == mpe->GetButtonStates()); } + +bool mitk::MousePressEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkMousePressEvent.h b/Core/Code/Interactions/mitkMousePressEvent.h index 53d7f6ce99..f15f3f15b4 100644 --- a/Core/Code/Interactions/mitkMousePressEvent.h +++ b/Core/Code/Interactions/mitkMousePressEvent.h @@ -1,58 +1,62 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKMOUSEPRESSEVENT_H_ #define MITKMOUSEPRESSEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEventConst.h" #include "mitkInteractionPositionEvent.h" #include "mitkBaseRenderer.h" #include "mitkInteractionEvent.h" #include namespace mitk { - class MITK_CORE_EXPORT MousePressEvent : public InteractionPositionEvent { + class MITK_CORE_EXPORT MousePressEvent: public InteractionPositionEvent + { public: - mitkClassMacro(MousePressEvent,InteractionPositionEvent); - mitkNewMacro5Param(Self, BaseRenderer*, Point2D , MouseButtons , ModifierKeys, MouseButtons); + mitkClassMacro(MousePressEvent,InteractionPositionEvent) + mitkNewMacro5Param(Self, BaseRenderer*, const Point2D , MouseButtons , ModifierKeys, MouseButtons) ModifierKeys GetModifiers() const; MouseButtons GetButtonStates() const; void SetModifiers(ModifierKeys modifiers); void SetButtonStates(MouseButtons buttons); - MouseButtons GetEventButton() const ; - void SetEventButton(MouseButtons buttons) ; + MouseButtons GetEventButton() const; + void SetEventButton(MouseButtons buttons); + virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: - MousePressEvent(BaseRenderer*, Point2D, MouseButtons buttonStates, ModifierKeys modifiers, MouseButtons eventButton); + MousePressEvent(BaseRenderer*, const Point2D = Point2D(), mitk::MouseButtons buttonStates = NoButton, mitk::ModifierKeys modifiers = + NoKey, mitk::MouseButtons eventButton = NoButton); virtual ~MousePressEvent(); private: MouseButtons m_EventButton; MouseButtons m_ButtonStates; ModifierKeys m_Modifiers; }; } /* namespace mitk */ #endif /* MITKMOUSEPRESSEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkMouseReleaseEvent.cpp b/Core/Code/Interactions/mitkMouseReleaseEvent.cpp index a9bebdb8bb..1a8a6d5354 100644 --- a/Core/Code/Interactions/mitkMouseReleaseEvent.cpp +++ b/Core/Code/Interactions/mitkMouseReleaseEvent.cpp @@ -1,78 +1,83 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkException.h" #include "mitkMouseReleaseEvent.h" mitk::MouseReleaseEvent::MouseReleaseEvent(mitk::BaseRenderer* baseRenderer, mitk::Point2D mousePosition, mitk::MouseButtons buttonStates, mitk::ModifierKeys modifiers, mitk::MouseButtons eventButton) : InteractionPositionEvent(baseRenderer, mousePosition, "MouseReleaseEvent") , m_EventButton(eventButton) ,m_ButtonStates(buttonStates) , m_Modifiers(modifiers) { } mitk::MouseButtons mitk::MouseReleaseEvent::GetEventButton() const { return m_EventButton; } void mitk::MouseReleaseEvent::SetEventButton(MouseButtons buttons) { m_EventButton = buttons; } mitk::ModifierKeys mitk::MouseReleaseEvent::GetModifiers() const { return m_Modifiers; } mitk::MouseButtons mitk::MouseReleaseEvent::GetButtonStates() const { return m_ButtonStates; } void mitk::MouseReleaseEvent::SetModifiers(ModifierKeys modifiers) { m_Modifiers = modifiers; } void mitk::MouseReleaseEvent::SetButtonStates(MouseButtons buttons) { m_ButtonStates = buttons; } mitk::MouseReleaseEvent::~MouseReleaseEvent() { } bool mitk::MouseReleaseEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { mitk::MouseReleaseEvent* mre = dynamic_cast(interactionEvent.GetPointer()); if (mre == NULL) { return false; } return (this->GetEventButton() == mre->GetEventButton() && this->GetModifiers() == mre->GetModifiers() && this->GetButtonStates() == mre->GetButtonStates() ); } + +bool mitk::MouseReleaseEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkMouseReleaseEvent.h b/Core/Code/Interactions/mitkMouseReleaseEvent.h index a74cc3ac73..966c4d70da 100644 --- a/Core/Code/Interactions/mitkMouseReleaseEvent.h +++ b/Core/Code/Interactions/mitkMouseReleaseEvent.h @@ -1,59 +1,65 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKMOUSERELEASEEVENT_H_ #define MITKMOUSERELEASEEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionPositionEvent.h" #include "mitkInteractionEventConst.h" #include "mitkBaseRenderer.h" #include "mitkInteractionEvent.h" #include namespace mitk { class MITK_CORE_EXPORT MouseReleaseEvent: public InteractionPositionEvent { public: - mitkClassMacro(MouseReleaseEvent,InteractionPositionEvent); - mitkNewMacro5Param(Self, BaseRenderer*, Point2D ,MouseButtons , ModifierKeys, MouseButtons) ; + mitkClassMacro(MouseReleaseEvent,InteractionPositionEvent) + mitkNewMacro5Param(Self, BaseRenderer*, const Point2D ,MouseButtons , ModifierKeys, MouseButtons) ModifierKeys GetModifiers() const; MouseButtons GetButtonStates() const; void SetModifiers(ModifierKeys modifiers); void SetButtonStates(MouseButtons buttons); MouseButtons GetEventButton() const; void SetEventButton(MouseButtons buttons); + virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: - MouseReleaseEvent(BaseRenderer*, Point2D, MouseButtons buttonStates, ModifierKeys modifiers, MouseButtons eventButton); + MouseReleaseEvent(BaseRenderer*, + mitk::Point2D mousePosition = Point2D(), + mitk::MouseButtons buttonStates = NoButton, + mitk::ModifierKeys modifiers = NoKey, + mitk::MouseButtons eventButton = NoButton); virtual ~MouseReleaseEvent(); private: MouseButtons m_EventButton; MouseButtons m_ButtonStates; ModifierKeys m_Modifiers; }; } /* namespace mitk */ #endif /* MITKMOUSERELEASEEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkMouseWheelEvent.cpp b/Core/Code/Interactions/mitkMouseWheelEvent.cpp index b97968007a..d81b1800e3 100644 --- a/Core/Code/Interactions/mitkMouseWheelEvent.cpp +++ b/Core/Code/Interactions/mitkMouseWheelEvent.cpp @@ -1,74 +1,79 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkMouseWheelEvent.h" mitk::MouseWheelEvent::MouseWheelEvent(BaseRenderer* baseRenderer, Point2D mousePosition, MouseButtons buttonStates, ModifierKeys modifiers, int wheelDelta) : InteractionPositionEvent(baseRenderer, mousePosition, "MouseWheelEvent") , m_WheelDelta(wheelDelta) , m_ButtonStates(buttonStates) , m_Modifiers(modifiers) { } int mitk::MouseWheelEvent::GetWheelDelta() const { return m_WheelDelta; } void mitk::MouseWheelEvent::SetWheelDelta(int delta) { m_WheelDelta = delta; } mitk::ModifierKeys mitk::MouseWheelEvent::GetModifiers() const { return m_Modifiers; } mitk::MouseButtons mitk::MouseWheelEvent::GetButtonStates() const { return m_ButtonStates; } void mitk::MouseWheelEvent::SetModifiers(ModifierKeys modifiers) { m_Modifiers = modifiers; } void mitk::MouseWheelEvent::SetButtonStates(MouseButtons buttons) { m_ButtonStates = buttons; } mitk::MouseWheelEvent::~MouseWheelEvent() { } bool mitk::MouseWheelEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { const mitk::MouseWheelEvent* mwe = dynamic_cast(interactionEvent.GetPointer()); if (mwe == NULL) { return false; } return ((this->GetWheelDelta() * mwe->GetWheelDelta() > 0) // Consider WheelEvents to be equal if the scrolling is done in the same direction. && this->GetModifiers() == mwe->GetModifiers() && this->GetButtonStates() == mwe->GetButtonStates()); } + +bool mitk::MouseWheelEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + return (dynamic_cast(baseClass.GetPointer()) != NULL) ; +} diff --git a/Core/Code/Interactions/mitkMouseWheelEvent.h b/Core/Code/Interactions/mitkMouseWheelEvent.h index 98c1ac7eee..deac97bb56 100644 --- a/Core/Code/Interactions/mitkMouseWheelEvent.h +++ b/Core/Code/Interactions/mitkMouseWheelEvent.h @@ -1,63 +1,68 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKMOUSEWHEELEVENT_H_ #define MITKMOUSEWHEELEVENT_H_ #include "itkObject.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include "mitkInteractionEventConst.h" #include "mitkInteractionPositionEvent.h" #include "mitkBaseRenderer.h" #include "mitkInteractionEvent.h" #include /** * Note: A Click with the MiddleButton is to be handled with MousePressEvents */ - namespace mitk { - class MITK_CORE_EXPORT MouseWheelEvent : public InteractionPositionEvent { + class MITK_CORE_EXPORT MouseWheelEvent: public InteractionPositionEvent + { public: - mitkClassMacro(MouseWheelEvent,InteractionPositionEvent); - mitkNewMacro5Param(Self, BaseRenderer*, Point2D , MouseButtons , ModifierKeys, int); + mitkClassMacro(MouseWheelEvent,InteractionPositionEvent) + mitkNewMacro5Param(Self, BaseRenderer*, const Point2D , MouseButtons , ModifierKeys, int) ModifierKeys GetModifiers() const; MouseButtons GetButtonStates() const; void SetModifiers(ModifierKeys modifiers); void SetButtonStates(MouseButtons buttons); int GetWheelDelta() const; void SetWheelDelta(int delta); virtual bool MatchesTemplate(InteractionEvent::Pointer); + virtual bool IsSuperClassOf(InteractionEvent::Pointer baseClass); protected: - MouseWheelEvent(BaseRenderer*, Point2D, MouseButtons buttonStates, ModifierKeys modifiers, int wheelDelta); + MouseWheelEvent(BaseRenderer* = NULL, + const Point2D mousePosition = Point2D(), + MouseButtons buttonStates = NoButton, + ModifierKeys modifiers = NoKey, + int wheelDelta = 0); virtual ~MouseWheelEvent(); private: int m_WheelDelta; MouseButtons m_ButtonStates; ModifierKeys m_Modifiers; }; } /* namespace mitk */ #endif /* MITKMOUSEPRESSEVENT_H_ */ diff --git a/Core/Code/Interactions/mitkPointSetDataInteractor.cpp b/Core/Code/Interactions/mitkPointSetDataInteractor.cpp index e8902028a7..c4c7416a21 100644 --- a/Core/Code/Interactions/mitkPointSetDataInteractor.cpp +++ b/Core/Code/Interactions/mitkPointSetDataInteractor.cpp @@ -1,304 +1,333 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPointSetDataInteractor.h" #include "mitkMouseMoveEvent.h" #include #include "mitkInteractionConst.h" // TODO: refactor file #include "mitkRenderingManager.h" #include "mitkInternalEvent.h" // #include "mitkDispatcher.h" #include "mitkBaseRenderer.h" void mitk::PointSetDataInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addpoint", AddPoint); CONNECT_FUNCTION("selectpoint", SelectPoint); CONNECT_FUNCTION("unselect", UnSelectPoint); CONNECT_FUNCTION("initMove", InitMove); CONNECT_FUNCTION("initMovePointSet", InitMoveAll); CONNECT_FUNCTION("movePoint", MovePoint); CONNECT_FUNCTION("movePointSet", MoveSet); CONNECT_FUNCTION("finishMovement", FinishMove); CONNECT_FUNCTION("removePoint", RemovePoint); } bool mitk::PointSetDataInteractor::AddPoint(StateMachineAction* stateMachineAction, InteractionEvent* interactionEvent) { // Find the position, the point is to be added to: first entry with // empty index. If the Set is empty, then start with 0. if not empty, // then take the first index which is not occupied int lastPosition = 0; PointSet::PointsContainer* pointsContainer = m_PointSet->GetPointSet(0)->GetPoints(); if (!pointsContainer->empty()) { mitk::PointSet::PointsIterator it, end; it = pointsContainer->Begin(); end = pointsContainer->End(); while (it != end) { if (!pointsContainer->IndexExists(lastPosition)) break; ++it; ++lastPosition; } } InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { IsClosedContour(stateMachineAction, interactionEvent); // Get time step from BaseRenderer int timeStep = positionEvent->GetSender()->GetTimeStep(); mitk::Point3D point = positionEvent->GetPositionInWorld(); m_PointSet->InsertPoint(lastPosition, point, timeStep); m_NumberOfPoints++; GetDataNode()->SetData(m_PointSet); GetDataNode()->Modified(); if (m_MaxNumberOfPoints != 0 && m_NumberOfPoints >= m_MaxNumberOfPoints) { InternalEvent::Pointer event = InternalEvent::New(NULL, this, "MaxNumberOfPoints"); positionEvent->GetSender()->GetDispatcher()->QueueEvent(event.GetPointer()); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } else { return false; } } bool mitk::PointSetDataInteractor::SelectPoint(StateMachineAction*, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { int timeStep = positionEvent->GetSender()->GetTimeStep(); Point3D point = positionEvent->GetPositionInWorld(); // iterate over point set and check if it contains a point close enough to the pointer to be selected if (GetPointIndexByPosition(point, timeStep) != -1) { //TODO FIXME is this safe ? can pointset and renderer have different sizes ? m_SelectedPointIndex = GetPointIndexByPosition(point, timeStep); GetDataNode()->SetProperty("contourcolor", ColorProperty::New(0.0, 0.0, 1.0)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } return false; } else { return false; } } mitk::PointSetDataInteractor::PointSetDataInteractor() : - m_NumberOfPoints(0), m_MaxNumberOfPoints(0),m_SelectedPointIndex(-1) + m_NumberOfPoints(0), m_MaxNumberOfPoints(0),m_SelectedPointIndex(-1),m_SelectionAccuracy(3.5) { } mitk::PointSetDataInteractor::~PointSetDataInteractor() { } bool mitk::PointSetDataInteractor::RemovePoint(StateMachineAction*, InteractionEvent*) { if (m_SelectedPointIndex != -1) { Point3D point; PointOperation* doOp = new PointOperation(mitk::OpREMOVE, point, m_SelectedPointIndex); GetDataNode()->GetData()->ExecuteOperation(doOp); m_SelectedPointIndex = -1; mitk::RenderingManager::GetInstance()->RequestUpdateAll(); m_NumberOfPoints--; return true; } else { return false; } } bool mitk::PointSetDataInteractor::IsClosedContour(StateMachineAction*, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { int timeStep = positionEvent->GetSender()->GetTimeStep(); Point3D point = positionEvent->GetPositionInWorld(); // iterate over point set and check if it contains a point close enough to the pointer to be selected if (GetPointIndexByPosition(point, timeStep) != -1 && m_PointSet->GetSize(timeStep) >= 3) { InternalEvent::Pointer event = InternalEvent::New(NULL, this, "ClosedContour"); positionEvent->GetSender()->GetDispatcher()->QueueEvent(event.GetPointer()); return true; } } return false; } bool mitk::PointSetDataInteractor::MovePoint(StateMachineAction* stateMachineAction, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { IsClosedContour(stateMachineAction, interactionEvent); // Get time step from BaseRenderer int timeStep = positionEvent->GetSender()->GetTimeStep(); mitk::Point3D point = positionEvent->GetPositionInWorld(); m_PointSet->SetPoint(m_SelectedPointIndex, point, timeStep); GetDataNode()->SetData(m_PointSet); GetDataNode()->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); IsClosedContour(stateMachineAction,interactionEvent); return true; } else { return false; } } bool mitk::PointSetDataInteractor::MoveSet(StateMachineAction*, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { int timeStep = positionEvent->GetSender()->GetTimeStep(); // Vector that represents movement relative to last position Point3D movementVector; movementVector[0] = positionEvent->GetPositionInWorld()[0] - m_PointSet->GetPoint(m_SelectedPointIndex, timeStep)[0]; movementVector[1] = positionEvent->GetPositionInWorld()[1] - m_PointSet->GetPoint(m_SelectedPointIndex, timeStep)[1]; movementVector[2] = positionEvent->GetPositionInWorld()[2] - m_PointSet->GetPoint(m_SelectedPointIndex, timeStep)[2]; PointSet* points = dynamic_cast(GetDataNode()->GetData()); PointSet::PointsContainer* pointsContainer = points->GetPointSet(timeStep)->GetPoints(); // Iterate over point set and update each point Point3D newPoint; for (PointSet::PointsIterator it = pointsContainer->Begin(); it != pointsContainer->End(); it++) { newPoint[0] = m_PointSet->GetPoint(it->Index(), timeStep)[0] + movementVector[0]; newPoint[1] = m_PointSet->GetPoint(it->Index(), timeStep)[1] + movementVector[1]; newPoint[2] = m_PointSet->GetPoint(it->Index(), timeStep)[2] + movementVector[2]; m_PointSet->SetPoint(it->Index(), newPoint, timeStep); } GetDataNode()->SetData(m_PointSet); GetDataNode()->Modified(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } else { return false; } } bool mitk::PointSetDataInteractor::UnSelectPoint(StateMachineAction*, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { int timeStep = positionEvent->GetSender()->GetTimeStep(); Point3D point = positionEvent->GetPositionInWorld(); // iterate over point set and check if it contains a point close enough to the pointer to be selected int index = GetPointIndexByPosition(point, timeStep); // here it is ensured that we don't switch from one point being selected to another one being selected, // without accepting the unselect of the current point if (index == -1 || index != m_SelectedPointIndex) { m_SelectedPointIndex = -1; GetDataNode()->SetProperty("contourcolor", ColorProperty::New(1.0, 0.0, 1.0)); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); return true; } return false; } else { return false; } } bool mitk::PointSetDataInteractor::Abort(StateMachineAction*, InteractionEvent* interactionEvent) { InternalEvent::Pointer event = InternalEvent::New(NULL, this, IntDeactivateMe); interactionEvent->GetSender()->GetDispatcher()->QueueEvent(event.GetPointer()); return true; } /* * Check whether the DataNode contains a pointset, if not create one and add it. */ void mitk::PointSetDataInteractor::DataNodeChanged() { if (GetDataNode().IsNotNull()) { // find proper place for this command! // maybe when DN is created ? GetDataNode()->SetBoolProperty("show contour", true); PointSet* points = dynamic_cast(GetDataNode()->GetData()); if (points == NULL) { m_PointSet = PointSet::New(); GetDataNode()->SetData(m_PointSet); } else { m_PointSet = points; } // load config file parameter: maximal number of points mitk::PropertyList::Pointer properties = GetAttributes(); std::string strNumber; if (properties->GetStringProperty("MaxPoints", strNumber)) { m_MaxNumberOfPoints = atoi(strNumber.c_str()); } } } bool mitk::PointSetDataInteractor::InitMove(StateMachineAction*, InteractionEvent*) { GetDataNode()->SetProperty("contourcolor", ColorProperty::New(1.0, 1.0, 1.0)); return true; } bool mitk::PointSetDataInteractor::FinishMove(StateMachineAction* stateMachineAction, InteractionEvent* interactionEvent) { IsClosedContour(stateMachineAction, interactionEvent); GetDataNode()->SetProperty("contourcolor", ColorProperty::New(1.0, 0.0, 0.0)); return true; } bool mitk::PointSetDataInteractor::InitMoveAll(StateMachineAction*, InteractionEvent* interactionEvent) { InteractionPositionEvent* positionEvent = dynamic_cast(interactionEvent); if (positionEvent != NULL) { m_LastMovePosition = positionEvent->GetPositionInWorld(); return true; } else { return false; } } + +void mitk::PointSetDataInteractor::SetAccuracy(float accuracy) +{ + m_SelectionAccuracy = accuracy; +} + +int mitk::PointSetDataInteractor::GetPointIndexByPosition(Point3D position, int time) +{ + + // iterate over point set and check if it contains a point close enough to the pointer to be selected + PointSet* points = dynamic_cast(GetDataNode()->GetData()); + int index = -1; + if (points == NULL) + { + return index; + } + PointSet::PointsContainer* pointsContainer = points->GetPointSet(time)->GetPoints(); + + float minDistance = m_SelectionAccuracy; + for (PointSet::PointsIterator it = pointsContainer->Begin(); it != pointsContainer->End(); it++) + { + float distance = sqrt(position.SquaredEuclideanDistanceTo(points->GetPoint(it->Index(), time))); // TODO: support time! + if (distance < minDistance) // if several points fall within the margin, choose the one with minimal distance to position + { // TODO: does this make sense, which unit is it? + index = it->Index(); + } + } + return index; +} diff --git a/Core/Code/Interactions/mitkPointSetDataInteractor.h b/Core/Code/Interactions/mitkPointSetDataInteractor.h index 4fbef1a603..75bee9b476 100644 --- a/Core/Code/Interactions/mitkPointSetDataInteractor.h +++ b/Core/Code/Interactions/mitkPointSetDataInteractor.h @@ -1,124 +1,141 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkPointSetDataInteractor_h_ #define mitkPointSetDataInteractor_h_ #include "itkObject.h" #include "itkSmartPointer.h" #include "itkObjectFactory.h" #include "mitkCommon.h" #include #include "mitkDataInteractor.h" #include namespace mitk { /** * Class PointSetDataInteractor * \brief Implementation of the PointSetInteractor * * Interactor operates on a point set and supports to: * - add points * - remove points * - move single points * - move complete pointset * - select/unselect a point * * in 2d and 3d render windows. */ // Inherit from DataInteratcor, this provides functionality of a state machine and configurable inputs. class MITK_CORE_EXPORT PointSetDataInteractor: public DataInteractor { public: - mitkClassMacro(PointSetDataInteractor, DataInteractor); - itkNewMacro(Self); + mitkClassMacro(PointSetDataInteractor, DataInteractor) + itkNewMacro(Self) protected: PointSetDataInteractor(); virtual ~PointSetDataInteractor(); /** * Here actions strings from the loaded state machine pattern are mapped to functions of * the DataInteractor. These functions are called when an action from the state machine pattern is executed. */ virtual void ConnectActionsAndFunctions(); /** * This function is called when a DataNode has been set/changed. * It is used to initialize the DataNode, e.g. if no PointSet exists yet it is created * and added to the DataNode. */ virtual void DataNodeChanged(); + + /** + * Sets the maximum distance that is accepted when looking for a point at a certain position using the GetPointIndexByPosition function. + */ + void SetAccuracy(float accuracy); + + /** + * @ brief Return index in PointSet of the point that is within given accuracy to the provided position. + * + * Assumes that the DataNode contains a PointSet, if so it iterates over all points + * in the DataNode to check if it contains a point near the pointer position. + * If a point is found its index-position is returned, else -1 is returned. + */ + virtual int GetPointIndexByPosition(Point3D position, int time = 0); + /** Adds a point at the given coordinates. * Every time a point is added it is also checked if the maximal number of points is reached, * and if so an InternalEvent with the signal name "MaxNumberOfPoints" is triggered. */ virtual bool AddPoint(StateMachineAction*, InteractionEvent*); /** Removes point that is selected */ virtual bool RemovePoint(StateMachineAction*, InteractionEvent*); /** * Checks if new point is close enough to an old one, * if so, trigger the ClosedContour signal which can be caught by the state machine. */ virtual bool IsClosedContour(StateMachineAction*, InteractionEvent*); /** * Moves the currenlty selected point to the new coodinates. */ virtual bool MovePoint(StateMachineAction*, InteractionEvent*); /** * Initializes the movement, stores starting position. */ virtual bool InitMove(StateMachineAction*, InteractionEvent*); /** * Is called when a movement is finished, changes back to regular color. */ virtual bool FinishMove(StateMachineAction*, InteractionEvent*); /** * Stores original position from which movement can be calculated. */ virtual bool InitMoveAll(StateMachineAction*, InteractionEvent*); /** * Moves all points of the PointSet by the same vector, which is the relative distance from the * initialization point. */ virtual bool MoveSet(StateMachineAction*, InteractionEvent*); /** * Selects a point from the PointSet as currently active. */ virtual bool SelectPoint(StateMachineAction*, InteractionEvent*); /** * Unselects a point, e.g. the pointer coordinates point to empty space. */ virtual bool UnSelectPoint(StateMachineAction*, InteractionEvent*); /** * Calls for inactivation of the DataInteractor */ virtual bool Abort(StateMachineAction*, InteractionEvent*); private: PointSet::Pointer m_PointSet; int m_NumberOfPoints; // to keep track of number of points in pointset int m_MaxNumberOfPoints; // maximum of allowed number of points int m_SelectedPointIndex; // index of currently selected point in PointSet /** member to keep track of PointSet movements */ Point3D m_LastMovePosition; + + float m_SelectionAccuracy; // accuracy that's needed to select a point }; } #endif diff --git a/Core/Code/Interactions/mitkPointSetInteractor.cpp b/Core/Code/Interactions/mitkPointSetInteractor.cpp index 4c7b60118f..1fbee816a6 100644 --- a/Core/Code/Interactions/mitkPointSetInteractor.cpp +++ b/Core/Code/Interactions/mitkPointSetInteractor.cpp @@ -1,1132 +1,1119 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPointSetInteractor.h" #include "mitkPointOperation.h" #include "mitkPositionEvent.h" #include "mitkPointSet.h" //#include "mitkStatusBar.h" #include "mitkDataNode.h" #include "mitkInteractionConst.h" #include "mitkAction.h" #include "mitkStateEvent.h" #include "mitkOperationEvent.h" #include "mitkUndoController.h" #include "mitkStateMachineFactory.h" #include "mitkStateTransitionOperation.h" #include "mitkBaseRenderer.h" #include "mitkRenderingManager.h" //how precise must the user pick the point //default value const int PRECISION = 5; mitk::PointSetInteractor ::PointSetInteractor(const char * type, DataNode* dataNode, int n) :Interactor(type, dataNode), m_Precision(PRECISION), m_N(n) { if (m_N==0) { STATEMACHINE_WARN<<"Instanciation of PointSetInteractor which takes care of 0 points does't make sense!\n"; STATEMACHINE_WARN<<"Setting number of points to 1!\n"; m_N = 1; } m_LastPoint.Fill(0); m_SumVec.Fill(0); this->InitAccordingToNumberOfPoints(); } mitk::PointSetInteractor::~PointSetInteractor() { } //##Documentation //## overwritten cause this class can handle it better! float mitk::PointSetInteractor::CanHandleEvent(StateEvent const* stateEvent) const { float returnValue = 0.0; //if it is a key event that can be handled in the current state, then return 0.5 mitk::DisplayPositionEvent const *disPosEvent = dynamic_cast (stateEvent->GetEvent()); - //Key event handling: if (disPosEvent == NULL) { //check, if the current state has a transition waiting for that key event. if (this->GetCurrentState()->GetTransition(stateEvent->GetId())!=NULL) - { - return 0.5; - } + {return 0.5;} else - { - return 0; - } + {return 0;} } - //on MouseMove do nothing! if (stateEvent->GetEvent()->GetType() == mitk::Type_MouseMove) - { - return 0; - } - + {return 0;} //get the time of the sender to look for the right transition. mitk::BaseRenderer* sender = stateEvent->GetEvent()->GetSender(); if (sender != NULL) { unsigned int timeStep = sender->GetTimeStep(m_DataNode->GetData()); //if the event can be understood and if there is a transition waiting for that event mitk::State const* state = this->GetCurrentState(timeStep); if (state!= NULL) if (state->GetTransition(stateEvent->GetId())!=NULL) returnValue = 0.5;//it can be understood - - mitk::PointSet *pointSet = dynamic_cast(m_DataNode->GetData()); if ( pointSet != NULL ) { //if we have one point or more, then check if the have been picked if ( (pointSet->GetSize( timeStep ) > 0) && (pointSet->SearchPoint( disPosEvent->GetWorldPosition(), m_Precision, timeStep) > -1) ) - { - returnValue = 1.0; - } + {returnValue = 1.0;} } } return returnValue; } //TODO: add a new calculation of precision here! Input: StateEvent and Precision //the method does a 2D picking with display coordinates and display geometry. //Here the distance between the mouse position and the point is not as relative anymore! //float mitk::PointSetInteractor::CalculatePrecision(float precision, mitk::StateEvent stateEvent) //{ // mitk::BaseRenderer *renderer = stateEvent->GetEvent()->GetSender(); // if (renderer != NULL) // { // const mitk::DisplayGeometry* displayGeometry = renderer->GetDisplayGeometry(); // if (displayGeometry != NULL) // displayGeometry->WorldToDisplay(, lineFrom); // precision = // } // // return precision; // //} void mitk::PointSetInteractor::UnselectAll( unsigned int timeStep, ScalarType timeInMS ) { mitk::PointSet *pointSet = dynamic_cast( m_DataNode->GetData() ); if ( pointSet == NULL ) { return; } mitk::PointSet::DataType *itkPointSet = pointSet->GetPointSet( timeStep ); if ( itkPointSet == NULL ) { return; } mitk::PointSet::PointsContainer::Iterator it, end; end = itkPointSet->GetPoints()->End(); for (it = itkPointSet->GetPoints()->Begin(); it != end; it++) { int position = it->Index(); PointSet::PointDataType pointData = {0, false, PTUNDEFINED}; itkPointSet->GetPointData( position, &pointData ); //then declare an operation which unselects this point; //UndoOperation as well! if ( pointData.selected ) { mitk::Point3D noPoint; noPoint.Fill( 0 ); mitk::PointOperation *doOp = new mitk::PointOperation( OpDESELECTPOINT, timeInMS, noPoint, position); if ( m_UndoEnabled ) { mitk::PointOperation *undoOp = new mitk::PointOperation(OpSELECTPOINT, timeInMS, noPoint, position); OperationEvent *operationEvent = new OperationEvent( pointSet, doOp, undoOp ); m_UndoController->SetOperationEvent( operationEvent ); } pointSet->ExecuteOperation( doOp ); if ( !m_UndoEnabled ) delete doOp; } } } void mitk::PointSetInteractor::SelectPoint( int position, unsigned int timeStep, ScalarType timeInMS ) { mitk::PointSet *pointSet = dynamic_cast< mitk::PointSet * >( m_DataNode->GetData() ); //if List is empty, then no select of a point can be done! if ( (pointSet == NULL) || (pointSet->GetSize( timeStep ) <= 0) ) { return; } //dummyPoint... not needed anyway mitk::Point3D noPoint; noPoint.Fill(0); mitk::PointOperation *doOp = new mitk::PointOperation( OpSELECTPOINT, timeInMS, noPoint, position); if ( m_UndoEnabled ) { mitk::PointOperation* undoOp = new mitk::PointOperation( OpDESELECTPOINT, timeInMS, noPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp); m_UndoController->SetOperationEvent(operationEvent); } pointSet->ExecuteOperation( doOp ); if ( !m_UndoEnabled ) delete doOp; } bool mitk::PointSetInteractor::ExecuteAction( Action* action, mitk::StateEvent const* stateEvent ) { bool ok = false;//for return type bool //checking corresponding Data; has to be a PointSet or a subclass mitk::PointSet* pointSet = dynamic_cast(m_DataNode->GetData()); if ( pointSet == NULL ) { return false; } //get the timestep to support 3D+T const mitk::Event *theEvent = stateEvent->GetEvent(); mitk::ScalarType timeInMS = 0.0; //check if the current timestep has to be changed if ( theEvent ) { if (theEvent->GetSender() != NULL) { //additionaly to m_TimeStep we need timeInMS to satisfy the execution of the operations timeInMS = theEvent->GetSender()->GetTime(); } } //for reading on the points, Id's etc mitk::PointSet::DataType *itkPointSet = pointSet->GetPointSet( m_TimeStep ); if ( itkPointSet == NULL ) { return false; } mitk::PointSet::PointsContainer *points = itkPointSet->GetPoints(); /*Each case must watch the type of the event!*/ switch (action->GetActionId()) { case AcDONOTHING: ok = true; break; case AcCHECKOPERATION: //to check if the given Event is a DisplayPositionEvent. { mitk::DisplayPositionEvent const *dispPosEvent = dynamic_cast ( stateEvent->GetEvent()); if (dispPosEvent != NULL) { mitk::StateEvent newStateEvent(EIDYES, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); } else { mitk::StateEvent newStateEvent(EIDNO, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); } ok = true; break; } case AcADDPOINT: // Declare two operations: one for the selected state: deselect the last // one selected and select the new one the other operation is the add // operation: There the first empty place have to be found and the new // point inserted into that space { mitk::DisplayPositionEvent const *posEvent = dynamic_cast < const mitk::DisplayPositionEvent * > (stateEvent->GetEvent()); // Check if it is a DisplayEvent thrown in a 3D window. Then the // z-information is missing. Returning false might end in the state // full, but the last point couldn't be added, so the set wouldn't be // full. So a extra Action that checks the operationtype has been added. if ( posEvent == NULL ) { return false; } mitk::Point3D itkPoint; itkPoint = posEvent->GetWorldPosition(); // undo-supported deselect of all points in the DataList; if List is // empty, then nothing will be unselected this->UnselectAll( m_TimeStep, timeInMS ); // find the position, the point is to be added to: first entry with // empty index. If the Set is empty, then start with 0. if not empty, // then take the first index not occupied int lastPosition = 0; if (!points->empty()) { mitk::PointSet::PointsIterator it, end; it = points->Begin(); end = points->End(); while( it != end ) { if (!points->IndexExists(lastPosition)) break; ++it; ++lastPosition; } } PointOperation* doOp = new mitk::PointOperation( OpINSERT, timeInMS, itkPoint, lastPosition); if (m_UndoEnabled) { // difference between OpDELETE and OpREMOVE is, that OpDELETE deletes // a point at the end, and OpREMOVE deletes it from the given position // remove is better, cause we need the position to add or remove the // point anyway. We can get the last position from size() PointOperation *undoOp = new mitk::PointOperation( OpREMOVE, timeInMS, itkPoint, lastPosition); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp, "Add point"); m_UndoController->SetOperationEvent(operationEvent); } //execute the Operation pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; //the point is added and directly selected in PintSet. So no need to call OpSELECTPOINT ok = true; // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcINITMOVEMENT: { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; // start of the Movement is stored to calculate the undoKoordinate // in FinishMovement m_LastPoint = posEvent->GetWorldPosition(); // initialize a value to calculate the movement through all // MouseMoveEvents from MouseClick to MouseRelease m_SumVec.Fill(0); ok = true; break; } case AcMOVESELECTED://moves all selected Elements { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; mitk::Point3D newPoint, resultPoint; newPoint = posEvent->GetWorldPosition(); // search the elements in the list that are selected then calculate the // vector, because only with the vector we can move several elements in // the same direction // newPoint - lastPoint = vector // then move all selected and set the lastPoint = newPoint. // then add all vectors to a summeryVector (to be able to calculate the // startpoint for undoOperation) mitk::Vector3D dirVector = newPoint - m_LastPoint; //sum up all Movement for Undo in FinishMovement m_SumVec = m_SumVec + dirVector; mitk::PointSet::PointsIterator it, end; it = points->Begin(); end = points->End(); while( it != end ) { int position = it->Index(); if ( pointSet->GetSelectInfo(position, m_TimeStep) )//if selected { PointSet::PointType pt = pointSet->GetPoint(position, m_TimeStep); mitk::Point3D sumVec; sumVec[0] = pt[0]; sumVec[1] = pt[1]; sumVec[2] = pt[2]; resultPoint = sumVec + dirVector; PointOperation doOp(OpMOVE, timeInMS, resultPoint, position); //execute the Operation //here no undo is stored, because the movement-steps aren't interesting. // only the start and the end is interisting to store for undo. pointSet->ExecuteOperation(&doOp); } ++it; } m_LastPoint = newPoint;//for calculation of the direction vector ok = true; // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcREMOVEPOINT://remove the given Point from the list { //if the point to be removed is given by the positionEvent: mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent != NULL) { mitk::Point3D itkPoint; itkPoint = posEvent->GetWorldPosition(); //search the point in the list int position = pointSet->SearchPoint(itkPoint, 0.0, m_TimeStep); //distance set to 0, cause we already got the exact point from last //State checkpointbut we also need the position in the list to remove it if (position>=0)//found a point { PointSet::PointType pt = pointSet->GetPoint(position, m_TimeStep); itkPoint[0] = pt[0]; itkPoint[1] = pt[1]; itkPoint[2] = pt[2]; //Undo PointOperation* doOp = new mitk::PointOperation(OpREMOVE, timeInMS, itkPoint, position); if (m_UndoEnabled) //write to UndoMechanism { PointOperation* undoOp = new mitk::PointOperation(OpINSERT, timeInMS, itkPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp, "Remove point"); m_UndoController->SetOperationEvent(operationEvent); } //execute the Operation pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; /*now select the point "position-1", and if it is the first in list, then contine at the last in list*/ //only then a select of a point is possible! if (pointSet->GetSize( m_TimeStep ) > 0) { if (position>0)//not the first in list { this->SelectPoint( position-1, m_TimeStep, timeInMS ); } //it was the first point in list, that was removed, so select //the last in list else { position = pointSet->GetSize( m_TimeStep ) - 1; //last in list this->SelectPoint( position, m_TimeStep, timeInMS ); }//else }//if ok = true; } } else //no position is given so remove all selected elements { //delete all selected points //search for the selected one and then declare the operations! mitk::PointSet::PointsContainer::Iterator it, end; it = points->Begin(); end = points->End(); int position = 0; int previousExistingPosition = -1;//to recognize the last existing position; needed because the iterator gets invalid if the point is deleted! int lastDelPrevExistPosition = -1; //the previous position of the last deleted point while (it != end) { if (points->IndexExists(it->Index())) { //if point is selected if ( pointSet->GetSelectInfo(it->Index(), m_TimeStep) ) { //get the coordinates of that point to be undoable PointSet::PointType selectedPoint = it->Value(); mitk::Point3D itkPoint; itkPoint[0] = selectedPoint[0]; itkPoint[1] = selectedPoint[1]; itkPoint[2] = selectedPoint[2]; position = it->Index(); PointOperation* doOp = new mitk::PointOperation(OpREMOVE, timeInMS, itkPoint, position); //Undo if (m_UndoEnabled) //write to UndoMechanism { PointOperation* undoOp = new mitk::PointOperation(OpINSERT, timeInMS, itkPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp, "Remove point"); m_UndoController->SetOperationEvent(operationEvent); } pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; //after delete the iterator is undefined, so start again //count to the last existing entry if (points->Size()>1 && points->IndexExists(previousExistingPosition)) { for (it = points->Begin(); it != points->End(); it++) { if (it->Index() == (unsigned int) previousExistingPosition) { lastDelPrevExistPosition = previousExistingPosition; break; //return if the iterator on the last existing position is found } } } else // size <= 1 or no previous existing position set { //search for the first existing position for (it = points->Begin(); it != points->End(); it++) if (points->IndexExists(it->Index())) { previousExistingPosition = it->Index(); break; } } //now that we have set the iterator, lets get sure, that the next it++ will not crash! if (it == end) { break; } }//if else { previousExistingPosition = it->Index(); } }//if index exists it++; }//while if (lastDelPrevExistPosition < 0)//the var has not been set because the first element was deleted and there was no prev position lastDelPrevExistPosition = previousExistingPosition; //go to the end /* * now select the point before the point/points that was/were deleted */ if (pointSet->GetSize( m_TimeStep ) > 0) //only then a select of a point is possible! { if (points->IndexExists(lastDelPrevExistPosition)) { this->SelectPoint( lastDelPrevExistPosition, m_TimeStep, timeInMS ); } else { //select the first existing element for (mitk::PointSet::PointsContainer::Iterator it = points->Begin(); it != points->End(); it++) if (points->IndexExists(it->Index())) { this->SelectPoint( it->Index(), m_TimeStep, timeInMS ); break; } } }//if ok = true; }//else }//case // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; // Remove all Points that have been set at once. // TODO: Undo function not supported yet. case AcREMOVEALL: { if ( !points->empty() ) { PointSet::PointType pt; mitk::PointSet::PointsContainer::Iterator it, end; it = points->Begin(); end = points->End(); int position = 0; while ( it != end ) { position = it->Index(); if ( points->IndexExists( position ) ) { pt = pointSet->GetPoint( position, m_TimeStep ); PointOperation doOp( OpREMOVE, timeInMS, pt, position ); ++it; pointSet->ExecuteOperation( &doOp ); } else it++; } } ok = true; // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } //Checking if the Point transmitted is close enough to one point. Then //generate a new event with the point and let this statemaschine //handle the event. case AcCHECKELEMENT: { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent != NULL) { mitk::Point3D worldPoint = posEvent->GetWorldPosition(); int position = pointSet->SearchPoint( worldPoint, m_Precision, m_TimeStep ); if (position>=0)//found a point near enough to the given point { //get that point, the one meant by the user! PointSet::PointType pt = pointSet->GetPoint(position, m_TimeStep); mitk::Point2D displPoint; displPoint[0] = worldPoint[0]; displPoint[1] = worldPoint[1]; //new Event with information YES and with the correct point mitk::PositionEvent newPosEvent(posEvent->GetSender(), Type_None, BS_NoButton, BS_NoButton, Key_none, displPoint, pt); mitk::StateEvent newStateEvent(EIDYES, &newPosEvent); //call HandleEvent to leave the guard-state this->HandleEvent( &newStateEvent ); ok = true; } else { //new Event with information NO mitk::StateEvent newStateEvent(EIDNO, posEvent); this->HandleEvent(&newStateEvent ); ok = true; } } else { MITK_DEBUG("OperationError")<GetType()<<" AcCHECKELEMENT expected PointOperation."; mitk::DisplayPositionEvent const *disPosEvent = dynamic_cast ( stateEvent->GetEvent()); if (disPosEvent != NULL) { //2d Koordinates for 3D Interaction; return false to redo //the last statechange mitk::StateEvent newStateEvent(EIDNO, disPosEvent); this->HandleEvent(&newStateEvent); ok = true; } } break; } case AcCHECKONESELECTED: //check if there is a point that is selected { if (pointSet->GetNumberOfSelected(m_TimeStep)>0) { mitk::StateEvent newStateEvent( EIDYES, theEvent); this->HandleEvent( &newStateEvent ); } else //not selected then call event EIDNO { //new Event with information NO mitk::StateEvent newStateEvent( EIDNO, theEvent); this->HandleEvent( &newStateEvent ); } ok = true; break; } case AcCHECKSELECTED: /*check, if the given point is selected: if no, then send EIDNO if yes, then send EIDYES*/ // check, if: because of the need to look up the point again, it is // possible, that we grab the wrong point in case there are two same points // so maybe we do have to set a global index for further computation, // as long, as the mouse is moved... { int position = -1; mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; mitk::Point3D worldPoint = posEvent->GetWorldPosition(); position = pointSet->SearchPoint(worldPoint, m_Precision, m_TimeStep); if (position>=0) { mitk::PositionEvent const *newPosEvent = new mitk::PositionEvent(posEvent->GetSender(), posEvent->GetType(), posEvent->GetButton(), posEvent->GetButtonState(), posEvent->GetKey(), posEvent->GetDisplayPosition(), posEvent->GetWorldPosition()); //if selected on true, then call Event EIDYES if (pointSet->GetSelectInfo(position, m_TimeStep)) { mitk::StateEvent newStateEvent( EIDYES, newPosEvent ); this->HandleEvent( &newStateEvent ); ok = true; //saving the spot for calculating the direction vector in moving m_LastPoint = posEvent->GetWorldPosition(); } else //not selected then call event EIDNO { //new Event with information NO mitk::StateEvent newStateEvent( EIDNO, newPosEvent ); this->HandleEvent( &newStateEvent ); ok = true; } delete newPosEvent; } //the position wasn't set properly. If necessary: search the given //point in list and set var position else { /* mitk::StatusBar::GetInstance()->DisplayText( "Message from mitkPointSetInteractor: Error in Actions! Check Config XML-file", 10000); */ ok = false; } break; } //generate Events if the set will be full after the addition of the // point or not. case AcCHECKNMINUS1: { // number of points not limited->pass on // "Amount of points in Set is smaller then N-1" if (m_N<0) { mitk::StateEvent newStateEvent(EIDSTSMALERNMINUS1, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } else { if (pointSet->GetSize( m_TimeStep ) < m_N-1 ) //pointset after addition won't be full { mitk::StateEvent newStateEvent(EIDSTSMALERNMINUS1, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } else //after the addition of a point, the container will be full { mitk::StateEvent newStateEvent(EIDSTLARGERNMINUS1, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; }//else }//else } break; case AcCHECKEQUALS1: { //the number of points in the list is 1 (or smaler) if (pointSet->GetSize( m_TimeStep ) <= 1) { mitk::StateEvent newStateEvent(EIDYES, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } else //more than 1 points in list, so stay in the state! { mitk::StateEvent newStateEvent(EIDNO, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } } break; case AcCHECKNUMBEROFPOINTS: { //the number of points in the list is 1 (or smaler), so will be empty after delete if (pointSet->GetSize( m_TimeStep ) <= 1) { mitk::StateEvent newStateEvent(EIDEMPTY, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } else if (pointSet->GetSize( m_TimeStep ) <= m_N || m_N <= -1) //m_N is set to unlimited points allowed or more than 1 points in list, but not full, so stay in the state! { // if the number of points equals m_N and no point of the point set is selected switch to state EIDEQUALSN if ((pointSet->GetSize( m_TimeStep ) == m_N)&&(pointSet->GetNumberOfSelected()==0)) { mitk::StateEvent newStateEvent(EIDEQUALSN, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } // if the number of points is small than or equal m_N and point(s) are selected stay in state else { mitk::StateEvent newStateEvent(EIDSMALLERN, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } } else //pointSet->GetSize( m_TimeStep ) >=m_N. // This can happen if the points were not added // by interaction but by loading a .mps file { mitk::StateEvent newStateEvent(EIDEQUALSN, stateEvent->GetEvent()); this->HandleEvent( &newStateEvent ); ok = true; } } break; case AcSELECTPICKEDOBJECT://and deselect others { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; mitk::Point3D itkPoint; itkPoint = posEvent->GetWorldPosition(); //search the point in the list int position = pointSet->SearchPoint(itkPoint, 0.0, m_TimeStep); //distance set to 0, cause we already got the exact point from last //State checkpoint but we also need the position in the list to move it if (position>=0)//found a point { //first deselect the other points //undoable deselect of all points in the DataList this->UnselectAll( m_TimeStep, timeInMS); PointOperation* doOp = new mitk::PointOperation(OpSELECTPOINT, timeInMS, itkPoint, position); //Undo if (m_UndoEnabled) //write to UndoMechanism { PointOperation* undoOp = new mitk::PointOperation(OpDESELECTPOINT, timeInMS, itkPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp); m_UndoController->SetOperationEvent(operationEvent); } //execute the Operation pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; ok = true; } // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcDESELECTOBJECT: { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; mitk::Point3D itkPoint; itkPoint = posEvent->GetWorldPosition(); //search the point in the list int position = pointSet->SearchPoint(itkPoint, 0.0, m_TimeStep); //distance set to 0, cause we already got the exact point from last // State checkpoint but we also need the position in the list to move it if (position>=0)//found a point { //Undo PointOperation* doOp = new mitk::PointOperation(OpDESELECTPOINT, timeInMS, itkPoint, position); if (m_UndoEnabled) //write to UndoMechanism { PointOperation* undoOp = new mitk::PointOperation(OpSELECTPOINT, timeInMS, itkPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp); m_UndoController->SetOperationEvent(operationEvent); } //execute the Operation pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; ok = true; } // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcDESELECTALL: { //undo-supported able deselect of all points in the DataList this->UnselectAll( m_TimeStep, timeInMS ); ok = true; // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcFINISHMOVEMENT: { mitk::PositionEvent const *posEvent = dynamic_cast (stateEvent->GetEvent()); if (posEvent == NULL) return false; //finish the movement: //the final point is m_LastPoint //m_SumVec stores the movement in a vector //the operation would not be necessary, but we need it for the undo Operation. //m_LastPoint is for the Operation //the point for undoOperation calculates from all selected //elements (point) - m_SumVec //search all selected elements and move them with undo-functionality. mitk::PointSet::PointsIterator it, end; it = points->Begin(); end = points->End(); while( it != end ) { int position = it->Index(); if ( pointSet->GetSelectInfo(position, m_TimeStep) )//if selected { PointSet::PointType pt = pointSet->GetPoint(position, m_TimeStep); Point3D itkPoint; itkPoint[0] = pt[0]; itkPoint[1] = pt[1]; itkPoint[2] = pt[2]; PointOperation* doOp = new mitk::PointOperation(OpMOVE, timeInMS, itkPoint, position); if ( m_UndoEnabled )//&& (posEvent->GetType() == mitk::Type_MouseButtonRelease) { //set the undo-operation, so the final position is undo-able //calculate the old Position from the already moved position - m_SumVec mitk::Point3D undoPoint = ( itkPoint - m_SumVec ); PointOperation* undoOp = new mitk::PointOperation(OpMOVE, timeInMS, undoPoint, position); OperationEvent *operationEvent = new OperationEvent(pointSet, doOp, undoOp, "Move point"); m_UndoController->SetOperationEvent(operationEvent); } //execute the Operation pointSet->ExecuteOperation(doOp); if ( !m_UndoEnabled ) delete doOp; } ++it; } //set every variable for movement calculation to zero // commented out: increases usebility in derived classes. /*m_LastPoint.Fill(0); m_SumVec.Fill(0);*/ //increase the GroupEventId, so that the Undo goes to here this->IncCurrGroupEventId(); ok = true; // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case AcCLEAR: { this->Clear( m_TimeStep, timeInMS ); // Update the display mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } default: return Superclass::ExecuteAction( action, stateEvent ); } // indicate modification of data tree node m_DataNode->Modified(); return ok; } void mitk::PointSetInteractor::Clear( unsigned int timeStep, ScalarType timeInMS ) { mitk::Point3D point; point.Fill(0); mitk::PointSet *pointSet = dynamic_cast(m_DataNode->GetData()); if ( pointSet == NULL ) { return; } mitk::PointSet::DataType *itkPointSet = pointSet->GetPointSet( timeStep ); if ( itkPointSet == NULL ) { return; } //for reading on the points, Id's etc mitk::PointSet::PointsContainer *points = itkPointSet->GetPoints(); mitk::PointSet::PointsIterator it, end; it = points->Begin(); end = points->End(); while( (it != end) && (pointSet->GetSize( timeStep ) > 0) ) { point = pointSet->GetPoint( it->Index(), timeStep ); PointOperation *doOp = new mitk::PointOperation( OpREMOVE, timeInMS, point, it->Index()); //write to UndoMechanism if ( m_UndoEnabled ) { PointOperation *undoOp = new mitk::PointOperation( OpINSERT, timeInMS, point, it->Index()); OperationEvent *operationEvent = new OperationEvent( pointSet, doOp, undoOp ); m_UndoController->SetOperationEvent( operationEvent ); } //execute the Operation ++it; pointSet->ExecuteOperation( doOp ); if ( !m_UndoEnabled ) delete doOp; } //reset the statemachine this->ResetStatemachineToStartState(timeStep); } void mitk::PointSetInteractor::InitAccordingToNumberOfPoints() { if (m_DataNode == NULL) return; mitk::PointSet *pointSet = dynamic_cast(m_DataNode->GetData()); if ( pointSet != NULL ) { //resize the CurrentStateVector this->ExpandStartStateVector(pointSet->GetPointSetSeriesSize()); for (unsigned int timestep = 0; timestep < pointSet->GetPointSetSeriesSize(); timestep++) { //go to new timestep this->UpdateTimeStep(timestep); int numberOfPoints = pointSet->GetSize( timestep ); if (numberOfPoints == 0) continue; //pointset is empty else { //we have a set of loaded points. Deselect all points, because they are all set to selected when added! this->UnselectAll(timestep); if (numberOfPointsHandleEvent( &newStateEvent ); } else if (numberOfPoints>=m_N) { if (numberOfPoints>m_N) { STATEMACHINE_WARN<<"Point Set contains more points than needed!\n";//display a warning that there are too many points } //get the currentState to state "Set full" const mitk::Event nullEvent(NULL, Type_User, BS_NoButton, BS_NoButton, Key_none); mitk::StateEvent newStateEvent(EIDEQUALSN, &nullEvent); this->HandleEvent( &newStateEvent ); } } } } return; } void mitk::PointSetInteractor::DataChanged() { this->InitAccordingToNumberOfPoints(); return; } diff --git a/Core/Code/Interactions/mitkPositionEvent.h b/Core/Code/Interactions/mitkPositionEvent.h index 306284fb9c..689d1d9c94 100644 --- a/Core/Code/Interactions/mitkPositionEvent.h +++ b/Core/Code/Interactions/mitkPositionEvent.h @@ -1,50 +1,55 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef POSITIONEVENT_H_HEADER_INCLUDED_C184F366 #define POSITIONEVENT_H_HEADER_INCLUDED_C184F366 #include #include "mitkDisplayPositionEvent.h" #include "mitkVector.h" namespace mitk { //##Documentation //## @brief Event that stores coordinates //## //## Stores display position of the mouse and 3D world position in mm. //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} mitk::PositionEvent is deprecated. Use mitk::InteractionPositionEvent instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ class MITK_CORE_EXPORT PositionEvent : public DisplayPositionEvent { public: //##Documentation //## @brief Constructor with all necessary arguments. //## //## @param sender: the widget, that caused that event, so that it can be asked for worldCoordinates. changed later to a focus //## @param type, button, buttonState, key: information from the Event //## @param displPosition: the 2D Position e.g. from the mouse //## @param worldPosition: the 3D position e.g. from a picking PositionEvent(BaseRenderer* sender, int type, int button, int buttonState, int key, const Point2D& displPosition, const Point3D& worldPosition); }; } // namespace mitk #endif /* POSITIONEVENT_H_HEADER_INCLUDED_C184F366 */ diff --git a/Core/Code/Interactions/mitkState.h b/Core/Code/Interactions/mitkState.h index b7530e3e5b..7c43113e0f 100755 --- a/Core/Code/Interactions/mitkState.h +++ b/Core/Code/Interactions/mitkState.h @@ -1,133 +1,134 @@ /*=================================================================== -The Medical Imaging Interaction Toolkit (MITK) + The Medical Imaging Interaction Toolkit (MITK) -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics. + All rights reserved. -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. + This software is distributed WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ + See LICENSE.txt or http://www.mitk.org for details. + ===================================================================*/ #ifndef STATE_H_HEADER_INCLUDED_C19A8A5D #define STATE_H_HEADER_INCLUDED_C19A8A5D #include #include #include #include #include #include #include #include "mitkTransition.h" -namespace mitk { +namespace mitk +{ /** - * @brief represents one state with all its necessary information - * - * Name and ID are stored. Also methods for building up, connecting and - * parsing for well formed statemachines are present. - * This class holds a map of transitions to next States. - * @ingroup Interaction - **/ - class MITK_CORE_EXPORT State : public itk::Object + * @brief represents one state with all its necessary information + * + * Name and ID are stored. Also methods for building up, connecting and + * parsing for well formed statemachines are present. + * This class holds a map of transitions to next States. + * @ingroup Interaction + * \deprecatedSince{2013_03} mitk::State is deprecated. Please use the mitk::StateMachineState instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + + class MITK_CORE_EXPORT State: public itk::Object { public: - mitkClassMacro(State, itk::Object); + mitkClassMacro(State, itk::Object) /** - * @brief static New method to use SmartPointer - **/ - mitkNewMacro2Param(Self, std::string, int); + * @brief static New method to use SmartPointer + **/ + mitkNewMacro2Param(Self, std::string, int) typedef std::map StateMap; typedef std::map > TransitionMap; typedef StateMap::iterator StateMapIter; typedef TransitionMap::iterator TransMapIter; typedef TransitionMap::const_iterator TransMapConstIter; /** - * @brief Add a transition to the map of transitions. - * - * Instances of all added transitions are freed in destructor of this class. - **/ - bool AddTransition( Transition* transition ); + * @brief Add a transition to the map of transitions. + * + * Instances of all added transitions are freed in destructor of this class. + **/ + bool AddTransition(Transition* transition); /** - * @brief hashmap-lookup and returning the Transition. Returns NULL Pointer if not located - **/ + * @brief hashmap-lookup and returning the Transition. Returns NULL Pointer if not located + **/ const Transition* GetTransition(int eventId) const; /** - * @brief Returns the name. - **/ + * @brief Returns the name. + **/ std::string GetName() const; /** - * @brief Returns the Id. - **/ + * @brief Returns the Id. + **/ int GetId() const; /** - * @brief Returns a set of all next States. E.g. to parse through all States. - **/ + * @brief Returns a set of all next States. E.g. to parse through all States. + **/ std::set GetAllNextStates() const; /** - * @brief Check, if this event (eventId) leads to a state. - **/ + * @brief Check, if this event (eventId) leads to a state. + **/ bool IsValidEvent(int eventId) const; /** - * @brief Searches dedicated States of all Transitions and sets *nextState of these Transitions. - * Required for this is a List of all build States of that StateMachine (allStates). This way the StateMachine can be build up. - **/ + * @brief Searches dedicated States of all Transitions and sets *nextState of these Transitions. + * Required for this is a List of all build States of that StateMachine (allStates). This way the StateMachine can be build up. + **/ bool ConnectTransitions(StateMap* allStates); protected: /** - * @brief Default Constructor. Use ::New instead! - * Set the name and the Id of the state. - * Name is to maintain readability during debug and Id is to identify this state inside the StateMachinePattern - **/ + * @brief Default Constructor. Use ::New instead! + * Set the name and the Id of the state. + * Name is to maintain readability during debug and Id is to identify this state inside the StateMachinePattern + **/ State(std::string name, int id); /** - * @brief Default Destructor - **/ + * @brief Default Destructor + **/ ~State(); private: /** - * @brief Name of this State to support readability during debug - **/ + * @brief Name of this State to support readability during debug + **/ std::string m_Name; /** - * @brief Id of this State important for interaction mechanism in StateMachinePattern - * - * All states inside a StateMachinePattern (construct of several states connected with transitions and actions) have to have an own id with which it is identifyable. - **/ + * @brief Id of this State important for interaction mechanism in StateMachinePattern + * + * All states inside a StateMachinePattern (construct of several states connected with transitions and actions) have to have an own id with which it is identifyable. + **/ int m_Id; /** - * @brief map of transitions that lead from this state to the next state - **/ + * @brief map of transitions that lead from this state to the next state + **/ TransitionMap m_Transitions; }; } // namespace mitk - - #endif /* STATE_H_HEADER_INCLUDED_C19A8A5D */ diff --git a/Core/Code/Interactions/mitkStateEvent.h b/Core/Code/Interactions/mitkStateEvent.h index 53d05e7f88..0326d07952 100644 --- a/Core/Code/Interactions/mitkStateEvent.h +++ b/Core/Code/Interactions/mitkStateEvent.h @@ -1,66 +1,72 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef STATEEVENT_H_HEADER_INCLUDED_C188E5BF #define STATEEVENT_H_HEADER_INCLUDED_C188E5BF #include namespace mitk { class Event; //##Documentation //## @brief Class holding an mitk-event and the mitk-event-number for a statechange //## //## Holds an event, with which a statechange of a statemachine shall be //## done. iD represents the mitk-event-number, event all further necessary information like //## the MousePosition or a key. //## Not derived from event to hold only one object stateevent, pass it to the statemachines, //## set the next event and reuse this object //## @ingroup Interaction + + /** + * \deprecatedSince{2013_03} mitk::StateEvent is deprecated. It becomes obsolete. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT StateEvent { public: StateEvent(); //##Documentation //## @brief Constructor //## @param id: mitk internal EventID //## @param event: the information about the appeared event StateEvent(int id, Event const* event = 0 ); ~StateEvent(); //##Documentation //## @brief to set the params and reuse an object void Set(int id, Event const* event); int GetId() const; mitk::Event const* GetEvent() const; private: int m_Id; mitk::Event const* m_Event; }; } // namespace mitk #endif /* STATEEVENT_H_HEADER_INCLUDED_C188E5BF */ diff --git a/Core/Code/Interactions/mitkStateMachine.h b/Core/Code/Interactions/mitkStateMachine.h index 52e389b291..1a7e848569 100644 --- a/Core/Code/Interactions/mitkStateMachine.h +++ b/Core/Code/Interactions/mitkStateMachine.h @@ -1,301 +1,307 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef STATEMACHINE_H_HEADER_INCLUDED_C18896BD #define STATEMACHINE_H_HEADER_INCLUDED_C18896BD #include #include #include "mitkOperationActor.h" #include #include "mitkState.h" #include "mitkUndoModel.h" namespace mitk { class Action; class StateEvent; class UndoController; // base class of statem machine functors + class MITK_CORE_EXPORT TStateMachineFunctor { public: virtual bool DoAction(Action*, const StateEvent*)=0; // call using function virtual ~TStateMachineFunctor() {} }; // the template functor for arbitrary StateMachine derivations template class TSpecificStateMachineFunctor : public TStateMachineFunctor { public: // constructor - takes pointer to an object and pointer to a member and stores // them in two private variables TSpecificStateMachineFunctor(T* object, bool(T::*memberFunctionPointer)(Action*, const StateEvent*)) :m_Object(object), m_MemberFunctionPointer(memberFunctionPointer) { } virtual ~TSpecificStateMachineFunctor() {} // virtual destructor // override function "Call" virtual bool DoAction(Action* action, const StateEvent* stateEvent) { return (*m_Object.*m_MemberFunctionPointer)(action, stateEvent); // execute member function } private: T* m_Object; // pointer to object bool (T::*m_MemberFunctionPointer)(Action*, const StateEvent*); // pointer to member function }; /// Can be uses by derived classes of StateMachine to connect action IDs to methods /// Assumes that there is a typedef Classname Self in classes that use this macro #define CONNECT_ACTION(a, f) \ StateMachine::AddActionFunction(a, new TSpecificStateMachineFunctor(this, &Self::f)); #define STATEMACHINE_INFO MITK_INFO("StateMachine") << "[type: " << GetType() << "] " #define STATEMACHINE_WARN MITK_WARN("StateMachine") << "[type: " << GetType() << "] " #define STATEMACHINE_FATAL MITK_FATAL("StateMachine") << "[type: " << GetType() << "] " #define STATEMACHINE_ERROR MITK_ERROR("StateMachine") << "[type: " << GetType() << "] " #define STATEMACHINE_DEBUG MITK_DEBUG("StateMachine") << "[type: " << GetType() << "] " /** @brief Superior statemachine @ingroup Interaction Realizes the methods, that every statemachine has to have. Undo can be enabled and disabled through EnableUndo. To implement your own state machine, you have to derive a class from mitk::StateMachine and either - override ExecuteAction() or - Write bool methods that take (Action*, const StateEvent*) as parameter and use the CONNECT_ACTION macro in your constructor The second version is recommended, since it provides more structured code. The following piece of code demonstrates how to use the CONNECT_ACTION macro. The important detail is to provide a typedef classname Self \code class LightSwitch : public StateMachine { public: mitkClassMacro(LightSwitch, StateMachine); // this creates the Self typedef LightSwitch(const char*); bool DoSwitchOn(Action*, const StateEvent*); bool DoSwitchOff(Action*, const StateEvent*); } LightSwitch::LightSwitch(const char* type) :StateMachine(type) { // make sure that AcSWITCHON and AcSWITCHOFF are defined int constants somewhere (e.g. mitkInteractionConst.h) CONNECT_ACTION( AcSWITCHON, DoSwitchOn ); CONNECT_ACTION( AcSWITCHOFF, DoSwitchOff ); } bool LightSwitch::DoSwitchOn(Action*, const StateEvent*) { std::cout << "Enlightenment" << std::endl; } bool LightSwitch::DoSwitchOff(Action*, const StateEvent*) { std::cout << "Confusion" << std::endl; } \endcode What CONNECT_ACTION does, is call StateMachine::AddActionFunction(...) to add some function pointer wrapping class (functor) to a std::map of StateMachine. Whenever StateMachines ExecuteAction is called, StateMachine will lookup the desired Action in its map and call the appropriate method in your derived class. **/ + /** + * \deprecatedSince{2013_03} mitk::StateMachine is deprecated. Use mitk::EventStateMachine instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT StateMachine : public itk::Object, public mitk::OperationActor { public: mitkClassMacro(StateMachine,itk::Object); /** * @brief New Macro with one parameter for creating this object with static New(..) method **/ mitkNewMacro1Param(Self, const char*); /** * @brief Map to connect action IDs with method calls. Use AddActionFunction or (even better) the CONNECT_ACTION macro to fill the map. **/ typedef std::map ActionFunctionsMapType; /** * @brief Type for a vector of StartStatePointers **/ typedef std::vector StartStateVectorType; /** * @brief Get the name and with this the type of the StateMachine **/ std::string GetType() const; /** * @brief handles an Event accordingly to its current State * * Statechange with Undo functionality; * EventMapper gives each event a new objectEventId * and a StateMachine::ExecuteAction can descide weather it gets a * new GroupEventId or not, depending on its state (e.g. finishedNewObject then new GroupEventId). * Object- and group-EventId can also be accessed through static methods from OperationEvent **/ virtual bool HandleEvent(StateEvent const* stateEvent); /** * @brief calculates how good this statemachine can handle the event. * * Returns a value between 0 and 1 * where 0 represents not responsible and 1 represents definitive responsible! * Standard function to override if needed. * (Used by GlobalInteraction to decide which DESELECTED statemachine to send the event to.) **/ virtual float CanHandleEvent(const StateEvent *) const; /** * @brief Enables or disabled Undo. **/ void EnableUndo(bool enable); /** * @brief A statemachine is also an OperationActor due to the UndoMechanism. * * The statechange is done in ExecuteOperation, so that the statechange can be undone by UndoMechanism. * Is set private here and in superclass it is set public, so UndoController * can reach ist, but it can't be overwritten by a subclass * *ATTENTION*: THIS METHOD SHOULD NOT BE CALLED FROM OTHER CLASSES DIRECTLY! **/ virtual void ExecuteOperation(Operation* operation); /** * @brief Friend so that UndoModel can call ExecuteOperation for Undo. **/ friend class UndoModel; friend class GlobalInteraction; protected: /** * @brief Default Constructor. Obsolete to instanciate it with this method! Use ::New(..) method instead. Set the "type" and with this the pattern of the StateMachine **/ StateMachine(const char * type); /** * @brief Default Destructor **/ ~StateMachine(); /** * @brief Adds the Function to ActionList. **/ void AddActionFunction(int action, TStateMachineFunctor* functor); /** * @brief Method called in HandleEvent after Statechange. * * Each statechange has actions, which can be assigned by it's number. * If you are developing a new statemachine, declare all your operations here and send them to Undo-Controller and to the Data. * Object- and group-EventId can also be accessed through static methods from OperationEvent **/ virtual bool ExecuteAction(Action* action, StateEvent const* stateEvent); /** * @brief returns the current state **/ const State* GetCurrentState(unsigned int timeStep = 0) const; /** * @brief if true, then UndoFunctionality is enabled * * Default value is true; **/ bool m_UndoEnabled; /** * @brief Friend protected function of OperationEvent; that way all StateMachines can set GroupEventId to be incremented! **/ void IncCurrGroupEventId(); /** * @brief holds an UndoController, that can be accessed from all StateMachines. For ExecuteAction **/ UndoController* m_UndoController; /** * @brief Resets the current state from the given timeStep to the StartState with undo functionality! Use carefully! * @param[in] timeStep If the statemachine has several timesteps to take care of, specify the according timestep **/ void ResetStatemachineToStartState(unsigned int timeStep = 0); /** * @brief Check if the number of timeSteps is equal to the number of stored StartStates. Nothing is changed if the number is equal. **/ void ExpandStartStateVector(unsigned int timeSteps); /** * @brief initializes m_CurrentStateVector **/ void InitializeStartStates(unsigned int timeSteps); /** * @brief Update the TimeStep of the statemachine with undo-support if undo enabled **/ virtual void UpdateTimeStep(unsigned int timeStep); /** * @brief Current TimeStep if the data which is to be interacted on, has more than 1 TimeStep **/ unsigned int m_TimeStep; private: /** * @brief The type of the StateMachine. This string specifies the StateMachinePattern that is loaded from the StateMachineFactory. **/ std::string m_Type; /** * @brief Points to the current state. **/ StartStateVectorType m_CurrentStateVector; /** * @brief Map of the added Functions **/ ActionFunctionsMapType m_ActionFunctionsMap; }; } // namespace mitk #endif /* STATEMACHINE_H_HEADER_INCLUDED_C18896BD */ diff --git a/Core/Code/Interactions/mitkStateMachineFactory.h b/Core/Code/Interactions/mitkStateMachineFactory.h index 333bf33fae..9840a80224 100755 --- a/Core/Code/Interactions/mitkStateMachineFactory.h +++ b/Core/Code/Interactions/mitkStateMachineFactory.h @@ -1,227 +1,232 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef STATEMACHINEFACTORY_H_HEADER_INCLUDED_C19AEDDD #define STATEMACHINEFACTORY_H_HEADER_INCLUDED_C19AEDDD #include #include "mitkState.h" #include "mitkTransition.h" #include "mitkAction.h" #include #include #include namespace mitk { /** *@brief builds up all specifiyed statemachines and hold them for later access * * According to the XML-File every different statemachine is build up. A new * instance of a new StateMachine grabs a StartState of one certain * state machine. Two instances of one kind of state machine share that * state machine. * During buildprocess at runtime each state machine is parsed for well formed style. * Currently different interaction styles are not yet supported. * To add individual state machine patterns, call LoadBehavior(...) * and it will be parsed added to the internal list of patterns * * @ingroup Interaction **/ + /** + * \deprecatedSince{2013_03} StateMachineFactory is deprecated. Please use mitk::StateMachineContainer instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT StateMachineFactory : public vtkXMLParser { public: static StateMachineFactory *New(); vtkTypeMacro(StateMachineFactory,vtkXMLParser); /** * @brief Typedef for all states that are defined as start-states **/ typedef std::map StartStateMap; typedef StartStateMap::iterator StartStateMapIter; /** * @brief Typedef to be used for parsing all states of one statemachine **/ typedef std::set HistorySet; typedef HistorySet::iterator HistorySetIter; /** * @brief This type holds all states of one statemachine. **/ typedef std::map StateMachineMapType; /** * @brief this type holds all states of all statemachines so that a specific state can be accessed for persistence **/ typedef std::map AllStateMachineMapType; /** * @brief Returns the StartState of the StateMachine with the name type; * * Returns NULL if no entry with name type is found. * Here a Smartpointer is returned to ensure, that StateMachines are also considered during reference counting. **/ State* GetStartState(const char* type); /** * @brief loads the xml file filename and generates the necessary instances **/ bool LoadBehavior(std::string fileName); /** * @brief loads the xml string and generates the necessary instances **/ bool LoadBehaviorString(std::string xmlString); /** * @brief Try to load standard behavior file "StateMachine.xml" * * Search strategy: * \li try environment variable "MITKCONF" (path to "StateMachine.xml") * \li try "./StateMachine.xml" * \li try via source directory (using MITKROOT from cmake-created * mitkConfig.h) "MITKROOT/Interactions/mitkBaseInteraction/StateMachine.xml" **/ bool LoadStandardBehavior(); const std::string& GetLastLoadedBehavior() { return m_LastLoadedBehavior; } /** * @brief Adds the given pattern to the internal list of patterns * * Method to support addition of externaly loaded patterns. * Instances of states, transitions and actions are maintained within this class and freed on destruction. * The states already have to be connected by transitions and actions and checked for errors. * @params type name of the pattern to add. Will be used during initialization of a new interactor. * @params startState the start state of this pattern. * @params allStatesOfStateMachine a map of state ids and its states to hold their reference and delete them in destructor **/ bool AddStateMachinePattern(const char * type, mitk::State* startState, StateMachineMapType* allStatesOfStateMachine); /** * brief To enable StateMachine to access states **/ friend class StateMachine; protected: /** * @brief Default Constructor **/ StateMachineFactory(); /** * @brief Default Destructor **/ ~StateMachineFactory(); /** * @brief Derived from XMLReader **/ void StartElement (const char* elementName, const char **atts); /** * @brief Derived from XMLReader **/ void EndElement (const char* elementName); private: /** * @brief Derived from XMLReader **/ std::string ReadXMLStringAttribut( std::string name, const char** atts); /** * @brief Derived from XMLReader **/ float ReadXMLFloatAttribut( std::string name, const char** atts ); /** * @brief Derived from XMLReader **/ double ReadXMLDoubleAttribut( std::string name, const char** atts ); /** * @brief Derived from XMLReader **/ int ReadXMLIntegerAttribut( std::string name, const char** atts ); /** * @brief Derived from XMLReader **/ bool ReadXMLBooleanAttribut( std::string name, const char** atts ); /** * @brief Returns a Pointer to the desired state if found. **/ mitk::State* GetState( const char* type, int StateId ); /** * @brief Sets the pointers in Transition (setNextState(..)) according to the extracted xml-file content **/ bool ConnectStates(mitk::State::StateMap* states); /** * @brief Recusive method, that parses this pattern of the stateMachine and returns true if correct **/ bool RParse(mitk::State::StateMap* states, mitk::State::StateMapIter thisState, HistorySet *history); /** * @brief Holds all created States that are defined as StartState **/ StartStateMap m_StartStates; /** * @brief Holds all States of one StateMachine to build up the pattern. **/ mitk::State::StateMap m_AllStatesOfOneStateMachine; /** * @brief A pointer to a State to help building up the pattern **/ State::Pointer m_AktState; /** * @brief A pointer to a Transition to help building up the pattern **/ itk::WeakPointer m_AktTransition; /** * @brief A pointer to an Action to help building up the pattern **/ Action::Pointer m_AktAction; /** * @brief map to hold all statemachines to call GetState for friends **/ AllStateMachineMapType m_AllStateMachineMap; std::string m_LastLoadedBehavior; std::string m_AktStateMachineName; /** * @brief Variable to skip a state machine pattern if the state machine name is not unique **/ bool m_SkipStateMachine; }; } // namespace mitk #endif /* STATEMACHINEFACTORY_H_HEADER_INCLUDED_C19AEDDD */ diff --git a/Core/Code/Interactions/mitkStateMachineState.cpp b/Core/Code/Interactions/mitkStateMachineState.cpp index f501131398..155b41cb57 100755 --- a/Core/Code/Interactions/mitkStateMachineState.cpp +++ b/Core/Code/Interactions/mitkStateMachineState.cpp @@ -1,86 +1,86 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkStateMachineState.h" mitk::StateMachineState::StateMachineState(std::string stateName, std::string stateMode) : m_Name(stateName), m_StateMode(stateMode) { } -std::string mitk::StateMachineState::GetMode() +std::string mitk::StateMachineState::GetMode() const { return m_StateMode; } mitk::StateMachineState::~StateMachineState() { m_Transitions.clear(); } bool mitk::StateMachineState::AddTransition(StateMachineTransition::Pointer transition) { for (TransitionVector::iterator it = m_Transitions.begin(); it != m_Transitions.end(); ++it) { if (transition.GetPointer() == (*it).GetPointer()) return false; } m_Transitions.push_back(transition); return true; } -mitk::StateMachineTransition::Pointer mitk::StateMachineState::GetTransition(std::string eventClass, std::string eventVariant) +mitk::StateMachineTransition::Pointer mitk::StateMachineState::GetTransition(const std::string eventClass, const std::string eventVariant) { mitk::StateMachineTransition::Pointer t = mitk::StateMachineTransition::New("", eventClass, eventVariant); for (TransitionVector::iterator it = m_Transitions.begin(); it != m_Transitions.end(); ++it) { if (**it == *t) // do not switch it and t, order matters, see mitk::StateMachineTransition == operator return *it; } return NULL; } -std::string mitk::StateMachineState::GetName() +std::string mitk::StateMachineState::GetName() const { return m_Name; } //##Documentation //## Post-processing step, when builing StateMachine from XML. //## Parse all transitions and find the State that matches the String-Name. bool mitk::StateMachineState::ConnectTransitions(StateMap *allStates) { for (TransitionVector::iterator transIt = m_Transitions.begin(); transIt != m_Transitions.end(); ++transIt) { bool found = false; for (StateMap::iterator stateIt = allStates->begin(); stateIt != allStates->end(); ++stateIt) { if ((*stateIt)->GetName() == (*transIt)->GetNextStateName()) { (*transIt)->SetNextState(*stateIt); found = true; break; } } if (!found) { MITK_WARN<< "Target State not found in StateMachine."; return false; // only reached if no state matching the string is found } } return true; } diff --git a/Core/Code/Interactions/mitkStateMachineState.h b/Core/Code/Interactions/mitkStateMachineState.h index 3d7a810b8a..b83c100ec1 100755 --- a/Core/Code/Interactions/mitkStateMachineState.h +++ b/Core/Code/Interactions/mitkStateMachineState.h @@ -1,86 +1,90 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef SMSTATE_H_HEADER_INCLUDED_C19A8A5D #define SMSTATE_H_HEADER_INCLUDED_C19A8A5D #include #include #include #include #include #include "mitkStateMachineTransition.h" namespace mitk { - - // Dispatcher and State Modes + /** + * \class StateMachineState + * Represents a state of a state machine pattern. + * It holds transitions to other states (mitk::StateMachineTransition) and the mode of the current state, see + * m_StateMode . + */ class MITK_CORE_EXPORT StateMachineState : public itk::Object { public: mitkClassMacro(StateMachineState, itk::Object); mitkNewMacro2Param(Self, std::string, std::string); typedef std::vector StateMap; typedef std::vector TransitionVector; bool AddTransition( StateMachineTransition::Pointer transition ); /** * @brief Return Transition which matches given event description. **/ - StateMachineTransition::Pointer GetTransition(std::string eventClass, std::string eventVariant); + StateMachineTransition::Pointer GetTransition(const std::string eventClass,const std::string eventVariant); /** * @brief Returns the name. **/ - std::string GetName(); + std::string GetName() const; - std::string GetMode(); + std::string GetMode() const; /** * @brief Searches dedicated States of all Transitions and sets *nextState of these Transitions. * Required for this is a List of all build States of that StateMachine (allStates). This way the StateMachine can be build up. **/ bool ConnectTransitions(StateMap* allStates); protected: StateMachineState(std::string name, std::string stateMode); ~StateMachineState(); private: /** * @brief Name of this State. **/ std::string m_Name; /** * State Modus, which determines the behavior of the dispatcher. A State can be in three different modes: * REGULAR - standard dispatcher behavior * GRAB_INPUT - all events are given to the statemachine in this modus, if they are not processed by this statemachine the events are dropped. * PREFER_INPUT - events are first given to this statemachine, and if not processed, offered to the other statemachines. */ std::string m_StateMode; /** * @brief map of transitions that lead from this state to the next state **/ TransitionVector m_Transitions; }; } // namespace mitk #endif /* SMSTATE_H_HEADER_INCLUDED_C19A8A5D */ diff --git a/Core/Code/Interactions/mitkStateMachineTransition.cpp b/Core/Code/Interactions/mitkStateMachineTransition.cpp index e8e73cf893..fcce659d99 100755 --- a/Core/Code/Interactions/mitkStateMachineTransition.cpp +++ b/Core/Code/Interactions/mitkStateMachineTransition.cpp @@ -1,96 +1,96 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkStateMachineTransition.h" #include "mitkStateMachineAction.h" #include "mitkStateMachineState.h" #include "mitkEventFactory.h" #include "mitkInteractionEventConst.h" mitk::StateMachineTransition::StateMachineTransition(std::string nextStateName, std::string eventClass, std::string eventVariant) : m_EventClass(eventClass), m_EventVariant(eventVariant), m_NextStateName(nextStateName) { PropertyList::Pointer propertyList = PropertyList::New(); propertyList->SetStringProperty(xmlParameterEventClass.c_str(), eventClass.c_str()); m_TransitionEvent = EventFactory::CreateEvent(propertyList); } -bool mitk::StateMachineTransition::operator ==(const StateMachineTransition& transition) +bool mitk::StateMachineTransition::operator ==(const StateMachineTransition& transition) const { // Create event based on incoming event type, // then try to cast it to the type of event that this transition holds, // if this is possible, the variant is checked // check for NULL since a corrupted state machine might cause an empty event if (m_TransitionEvent.IsNull()) { return false; } PropertyList::Pointer propertyList = PropertyList::New(); propertyList->SetStringProperty(xmlParameterEventClass.c_str(), transition.m_EventClass.c_str()); InteractionEvent::Pointer tmpEvent = EventFactory::CreateEvent(propertyList); if (tmpEvent.IsNull()) { return false; } - if (tmpEvent->IsSubClassOf(m_TransitionEvent.GetPointer())) + if (m_TransitionEvent->IsSuperClassOf(tmpEvent.GetPointer())) { return (this->m_EventVariant == transition.m_EventVariant); } else { // if event variants match, but super class condition is violated // this means that the configuration file, implements a class that does not // support the type in the state machine. if (this->m_EventVariant == transition.m_EventVariant) { MITK_WARN<< "Event type in Statemachine " << m_EventClass << " is not compatible to configuration class " << transition.m_EventClass; } return false; } } mitk::StateMachineTransition::~StateMachineTransition() { //needed for correct reference counting of mitkState//, for real??? m_NextState = NULL; m_Actions.clear(); } void mitk::StateMachineTransition::AddAction(StateMachineAction::Pointer action) { m_Actions.push_back(action); } -mitk::StateMachineState::Pointer mitk::StateMachineTransition::GetNextState() +mitk::StateMachineState::Pointer mitk::StateMachineTransition::GetNextState() const { return m_NextState; } std::string mitk::StateMachineTransition::GetNextStateName() const { return m_NextStateName; } std::vector mitk::StateMachineTransition::GetActions() const { return m_Actions; } void mitk::StateMachineTransition::SetNextState(SpStateMachineState nextState) { m_NextState = nextState; } diff --git a/Core/Code/Interactions/mitkStateMachineTransition.h b/Core/Code/Interactions/mitkStateMachineTransition.h index a533ef0532..fdc94e2802 100755 --- a/Core/Code/Interactions/mitkStateMachineTransition.h +++ b/Core/Code/Interactions/mitkStateMachineTransition.h @@ -1,94 +1,94 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef SMTRANSITION_H_HEADER_INCLUDED #define SMTRANSITION_H_HEADER_INCLUDED #include #include "mitkCommon.h" #include #include #include #include "mitkStateMachineAction.h" #include "mitkInteractionEvent.h" namespace mitk { class StateMachineState; typedef std::vector ActionVectorType; typedef itk::SmartPointer SpStateMachineState; /** * \class StateMachineTransition * @brief Connects two states, and holds references to actions that are executed on transition. * * @ingroup Interaction **/ class MITK_CORE_EXPORT StateMachineTransition: public itk::Object { public: mitkClassMacro(StateMachineTransition, itk::Object); mitkNewMacro3Param(Self, std::string,std::string,std::string); void AddAction(StateMachineAction::Pointer action); - SpStateMachineState GetNextState(); + SpStateMachineState GetNextState() const; std::string GetNextStateName() const; /** * Check for equality. Equality is given if event variant is the same and * classes are the same or the first argument is a superclass of the second. * \warn Here the order of arguments matters. ! */ - bool operator==(const StateMachineTransition& transition); + bool operator==(const StateMachineTransition& transition) const; /** * @brief Get an iterator on the first action in list. **/ ActionVectorType GetActions() const; /** * @brief Set the next state of this object. **/ void SetNextState(SpStateMachineState nextState); protected: StateMachineTransition(std::string nextStateName, std::string eventClass, std::string eventVariant); virtual ~StateMachineTransition(); // Triggering Event std::string m_EventClass; std::string m_EventVariant; private: SpStateMachineState m_NextState; std::string m_NextStateName; InteractionEvent::Pointer m_TransitionEvent; /** * @brief The list of actions, that are executed if this transition is done. **/ std::vector m_Actions; }; } // namespace mitk #endif /* SMTRANSITION_H_HEADER_INCLUDED */ diff --git a/Core/Code/Interactions/mitkTransition.h b/Core/Code/Interactions/mitkTransition.h index d4233365ae..ce9cfb5132 100755 --- a/Core/Code/Interactions/mitkTransition.h +++ b/Core/Code/Interactions/mitkTransition.h @@ -1,140 +1,144 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef TRANSITION_H_HEADER_INCLUDED_C19AE06B #define TRANSITION_H_HEADER_INCLUDED_C19AE06B #include #include #include #include #include "mitkAction.h" namespace mitk { class State; /** * @brief Connection of two states * * A transition connects two states. * Several actions are stored, that have to be executed after the statechange. * @ingroup Interaction - **/ + * + * \deprecatedSince{2013_03} mitk::Transition is deprecated. Use mitk::StateMachineTransition instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT Transition { public: typedef std::vector< mitk::Action::Pointer > ActionVectorType; typedef ActionVectorType::iterator ActionVectorIterator; typedef const ActionVectorIterator ActionVectorConstIterator; /** * @brief Add the action to this object. **/ void AddAction( Action* action ); /** * @brief Return the name of this object. **/ std::string GetName() const; /** * @brief Get the next state of this object. **/ State* GetNextState() const; /** * @brief Get the Id of the next state of this object. **/ int GetNextStateId() const; /** * @brief Get the eventId of this object. **/ int GetEventId() const; /** * @brief Get the number of actions. **/ unsigned int GetActionCount() const; /** * @brief Get an interator on the first action in list. **/ ActionVectorIterator GetActionBeginIterator() const; /** * @brief Get an interator behind the last action in list. **/ ActionVectorConstIterator GetActionEndIterator() const; /** * @brief Returns true if the given eventId is equal to this eventId. **/ bool IsEvent(int eventId) const; /** * @brief Set the next state of this object. **/ void SetNextState(State* state); /** * @brief Default Constructor * Sets the necessary informations name (to enhance readability during debug), * nextStateId (the Id of the next state) and eventId (the Id of the event that causes the statechange). **/ Transition(std::string name, int nextStateId, int eventId); /** * @brief Default Denstructor **/ ~Transition(); private: /** * @brief For better debugging and reading it stores the name of this. **/ std::string m_Name; /** * @brief a Pointer to the next state of this object. **/ itk::WeakPointer m_NextState; /** * @brief The Id of the next state. **/ int m_NextStateId; /** * @brief The eventId which is associated to this object. **/ int m_EventId; /** * @brief The list of actions, that are executed if this transition is done. **/ mutable std::vector m_Actions; }; } // namespace mitk #endif /* TRANSITION_H_HEADER_INCLUDED_C19AE06B */ diff --git a/Core/Code/Interactions/mitkVtkEventAdapter.h b/Core/Code/Interactions/mitkVtkEventAdapter.h index 7ba8e0e22e..4fc6265f35 100644 --- a/Core/Code/Interactions/mitkVtkEventAdapter.h +++ b/Core/Code/Interactions/mitkVtkEventAdapter.h @@ -1,81 +1,81 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKVTKEVENTADAPTER_H_ #define MITKVTKEVENTADAPTER_H_ // INTERACTION LEGACY #include #include #include #include "mitkMousePressEvent.h" #include "mitkMouseReleaseEvent.h" #include "mitkMouseMoveEvent.h" #include "mitkMouseWheelEvent.h" #include "mitkInteractionKeyEvent.h" #include "vtkRenderWindowInteractor.h" //##Documentation //## @brief Generates MITK events from VTK //## //## This class is the NON-QT dependent pendant to QmitkEventAdapter. //## It provides static functions to set up MITK events from VTK source data //## //## @ingroup Interaction namespace mitk { class BaseRenderer; class MITK_EXPORT VtkEventAdapter { public: /** - * \deprecated{Please switch to the appropriate AdaptMousePress/Move/Release-Event function.} + \deprecatedSince{2013_03} This method can be replaced by mitk::AdaptMousePressEvent / mitk::AdaptMouseMoveEvent / mitk::AdaptMouseReleaseEvent + */ + DEPRECATED(static mitk::MouseEvent AdaptMouseEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi)); + /** + \deprecatedSince{2013_03} This method can be replaced by mitk::AdaptMouseWheelEvent */ - static mitk::MouseEvent AdaptMouseEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); - /** - * \deprecated{Please switch to the AdaptMouseWheelEvent function.} - */ - static mitk::WheelEvent AdaptWheelEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); - /** - * \deprecated{Please switch to the AdaptInteractionKeyEvent function.} + DEPRECATED(static mitk::WheelEvent AdaptWheelEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi)); + /** + \deprecatedSince{2013_03} This method can be replaced by mitk::AdaptInteractionKeyEvent */ - static mitk::KeyEvent AdaptKeyEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); + DEPRECATED(static mitk::KeyEvent AdaptKeyEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi)); /** New events compatible with the revised interaction scheme */ static mitk::MousePressEvent::Pointer AdaptMousePressEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); static mitk::MouseMoveEvent::Pointer AdaptMouseMoveEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); static mitk::MouseReleaseEvent::Pointer AdaptMouseReleaseEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); static mitk::MouseWheelEvent::Pointer AdaptMouseWheelEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); static mitk::InteractionKeyEvent::Pointer AdaptInteractionKeyEvent(mitk::BaseRenderer* sender, unsigned long vtkCommandEventId,vtkRenderWindowInteractor* rwi); /** * Vtk events do not provide a button state for MouseMove events, therefore this map is used to keep a record of the * button state, which then can be used to provide information for MITK MouseMove events. */ static std::map buttonStateMap; }; } #endif /*QMITKEVENTADAPTER_H_*/ diff --git a/Core/Code/Interactions/mitkWheelEvent.h b/Core/Code/Interactions/mitkWheelEvent.h index 79ca75c1d2..4425703d26 100644 --- a/Core/Code/Interactions/mitkWheelEvent.h +++ b/Core/Code/Interactions/mitkWheelEvent.h @@ -1,55 +1,60 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef WheelEvent_H_HEADER_INCLUDED_C184F366 #define WheelEvent_H_HEADER_INCLUDED_C184F366 #include #include "mitkDisplayPositionEvent.h" #include "mitkVector.h" namespace mitk { //##Documentation //## @brief Event that stores coordinates and rotation on mouse wheel events //## //## Stores display position of the mouse and 3D world position in mm. //## @ingroup Interaction + /** + * \deprecatedSince{2013_03} mitk::WheelEvent is deprecated. Use mitk::MouseWheelEvent instead. + * Refer to \see DataInteractionPage for general information about the concept of the new implementation. + */ + class MITK_CORE_EXPORT WheelEvent : public DisplayPositionEvent { public: //##Documentation //## @brief Constructor with all necessary arguments. //## //## @param sender: the widget, that caused that event, so that it can be asked for worldCoordinates. changed later to a focus //## @param type, button, buttonState, key: information from the Event //## @param displPosition: the 2D Position e.g. from the mouse //## @param worldPosition: the 3D position e.g. from a picking //## @param delta: the movement of the mousewheel WheelEvent(BaseRenderer* sender, int type, int button, int buttonState, int key, const Point2D& displPosition, int delta); int GetDelta() const; protected: int m_Delta; }; } // namespace mitk #endif /* WheelEvent_H_HEADER_INCLUDED_C184F366 */ diff --git a/Core/Code/Interactions/mitkEventObserver.cpp b/Core/Code/Interfaces/mitkInteractionEventObserver.cpp similarity index 60% rename from Core/Code/Interactions/mitkEventObserver.cpp rename to Core/Code/Interfaces/mitkInteractionEventObserver.cpp index cda48cae0d..785f1ef263 100644 --- a/Core/Code/Interactions/mitkEventObserver.cpp +++ b/Core/Code/Interfaces/mitkInteractionEventObserver.cpp @@ -1,34 +1,22 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkEventObserver.h" +#include "mitkInteractionEventObserver.h" -void mitk::EventObserver::Notify(InteractionEvent::Pointer /*interactionEvent*/, bool /*isHandled*/) -{ -} - -mitk::EventObserver::EventObserver() -{ -} - -mitk::EventObserver::~EventObserver() -{ -} -bool mitk::EventObserver::FilterEvents(InteractionEvent* /*interactionEvent*/, DataNode* /*dataNode*/) +mitk::InteractionEventObserver::~InteractionEventObserver() { - return true; } diff --git a/Core/Code/Interactions/mitkEventObserver.h b/Core/Code/Interfaces/mitkInteractionEventObserver.h similarity index 58% rename from Core/Code/Interactions/mitkEventObserver.h rename to Core/Code/Interfaces/mitkInteractionEventObserver.h index fd479a0238..49f44208fc 100644 --- a/Core/Code/Interactions/mitkEventObserver.h +++ b/Core/Code/Interfaces/mitkInteractionEventObserver.h @@ -1,80 +1,62 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef EventObserver_h -#define EventObserver_h +#ifndef InteractionEventObserver_h +#define InteractionEventObserver_h -#include "itkObject.h" -#include "itkObjectFactory.h" -#include "mitkCommon.h" -#include "mitkEventStateMachine.h" -#include "mitkInteractionEvent.h" #include +#include "mitkServiceInterface.h" +#include "mitkInteractionEvent.h" namespace mitk { /** - * \class EventObserver - * \brief Base class to implement EventObservers. + * \class InteractionEventObserver + * \brief Base class to implement InteractionEventObservers. * * This class also provides state machine infrastructure, * but usage thereof is optional. See the Notify method for more information. */ - class MITK_CORE_EXPORT EventObserver : public EventStateMachine { - - public: - mitkClassMacro(EventObserver,EventHandler); - itkNewMacro(Self); - /** + struct MITK_CORE_EXPORT InteractionEventObserver + { + virtual ~InteractionEventObserver(); + /** * By this method all registered EventObersers are notified about every InteractionEvent, * the isHandled flag indicates if a DataInteractor has already handled that event. - * EventObserver that trigger an action when observing an event may consider + * InteractionEventObserver that trigger an action when observing an event may consider * this in order to not confuse the user by, triggering several independent action with one * single user event (such as a mouse click) * - * If you want to use the EventObserver as a state machine give the event to the state machine by implementing, e.g. + * If you want to use the InteractionEventObserver as a state machine give the event to the state machine by implementing, e.g. \code - void mitk::EventObserver::Notify(InteractionEvent::Pointer interactionEvent, bool isHandled) + void mitk::InteractionEventObserver::Notify(InteractionEvent::Pointer interactionEvent, bool isHandled) { if (!isHandled) { this->HandleEvent(interactionEvent, NULL); } } \endcode - */ - virtual void Notify(InteractionEvent::Pointer interactionEvent,bool isHandled); - - protected: - EventObserver(); - virtual ~EventObserver(); - - /** - * This overwrites the FilterEvents function of the EventStateMachine to ignore the DataNode, since EventObservers are not associated with one. - */ + * This overwrites the FilterEvents function of the EventStateMachine to ignore the DataNode, since InteractionEventObservers are not associated with one. virtual bool FilterEvents(InteractionEvent* interactionEvent, DataNode* dataNode); - - protected: - - - private: - + */ + virtual void Notify(InteractionEvent* interactionEvent,bool isHandled) = 0; }; } /* namespace mitk */ - -#endif /* EventObserver_h */ +US_DECLARE_SERVICE_INTERFACE(mitk::InteractionEventObserver, "org.mitk.InteractionEventObserver") +#endif /* InteractionEventObserver_h */ diff --git a/Core/Code/Rendering/mitkBaseRenderer.cpp b/Core/Code/Rendering/mitkBaseRenderer.cpp index 845a0b27e2..0e1015498e 100644 --- a/Core/Code/Rendering/mitkBaseRenderer.cpp +++ b/Core/Code/Rendering/mitkBaseRenderer.cpp @@ -1,830 +1,835 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBaseRenderer.h" #include "mitkMapper.h" #include "mitkResliceMethodProperty.h" // Geometries #include "mitkPlaneGeometry.h" #include "mitkSlicedGeometry3D.h" // Controllers #include "mitkCameraController.h" #include "mitkSliceNavigationController.h" #include "mitkCameraRotationController.h" #include "mitkVtkInteractorCameraController.h" #ifdef MITK_USE_TD_MOUSE #include "mitkTDMouseVtkCameraController.h" #else #include "mitkCameraController.h" #endif #include "mitkVtkLayerController.h" // Events // TODO: INTERACTION_LEGACY #include "mitkEventMapper.h" #include "mitkGlobalInteraction.h" #include "mitkPositionEvent.h" #include "mitkDisplayPositionEvent.h" #include "mitkProperties.h" #include "mitkWeakPointerProperty.h" #include "mitkInteractionConst.h" // VTK #include #include #include #include #include #include #include mitk::BaseRenderer::BaseRendererMapType mitk::BaseRenderer::baseRendererMap; mitk::BaseRenderer* mitk::BaseRenderer::GetInstance(vtkRenderWindow * renWin) { for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++) { if ((*mapit).first == renWin) return (*mapit).second; } return NULL; } void mitk::BaseRenderer::AddInstance(vtkRenderWindow* renWin, BaseRenderer* baseRenderer) { if (renWin == NULL || baseRenderer == NULL) return; // ensure that no BaseRenderer is managed twice mitk::BaseRenderer::RemoveInstance(renWin); baseRendererMap.insert(BaseRendererMapType::value_type(renWin, baseRenderer)); } void mitk::BaseRenderer::RemoveInstance(vtkRenderWindow* renWin) { BaseRendererMapType::iterator mapit = baseRendererMap.find(renWin); if (mapit != baseRendererMap.end()) baseRendererMap.erase(mapit); } mitk::BaseRenderer* mitk::BaseRenderer::GetByName(const std::string& name) { for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++) { if ((*mapit).second->m_Name == name) return (*mapit).second; } return NULL; } vtkRenderWindow* mitk::BaseRenderer::GetRenderWindowByName(const std::string& name) { for (BaseRendererMapType::iterator mapit = baseRendererMap.begin(); mapit != baseRendererMap.end(); mapit++) { if ((*mapit).second->m_Name == name) return (*mapit).first; } return NULL; } mitk::BaseRenderer::BaseRenderer(const char* name, vtkRenderWindow * renWin, mitk::RenderingManager* rm) : m_RenderWindow(NULL), m_VtkRenderer(NULL), m_MapperID(defaultMapper), m_DataStorage(NULL), m_RenderingManager(rm), m_LastUpdateTime(0), m_CameraController( NULL), m_SliceNavigationController(NULL), m_CameraRotationController(NULL), /*m_Size(),*/ m_Focused(false), m_WorldGeometry(NULL), m_TimeSlicedWorldGeometry(NULL), m_CurrentWorldGeometry(NULL), m_CurrentWorldGeometry2D(NULL), m_DisplayGeometry( NULL), m_Slice(0), m_TimeStep(), m_CurrentWorldGeometry2DUpdateTime(), m_DisplayGeometryUpdateTime(), m_TimeStepUpdateTime(), m_WorldGeometryData( NULL), m_DisplayGeometryData(NULL), m_CurrentWorldGeometry2DData(NULL), m_WorldGeometryNode(NULL), m_DisplayGeometryNode(NULL), m_CurrentWorldGeometry2DNode( NULL), m_DisplayGeometryTransformTime(0), m_CurrentWorldGeometry2DTransformTime(0), m_Name(name), /*m_Bounds(),*/m_EmptyWorldGeometry( true), m_DepthPeelingEnabled(true), m_MaxNumberOfPeels(100), m_NumberOfVisibleLODEnabledMappers(0) { m_Bounds[0] = 0; m_Bounds[1] = 0; m_Bounds[2] = 0; m_Bounds[3] = 0; m_Bounds[4] = 0; m_Bounds[5] = 0; if (name != NULL) { m_Name = name; } else { m_Name = "unnamed renderer"; itkWarningMacro(<< "Created unnamed renderer. Bad for serialization. Please choose a name."); } if (renWin != NULL) { m_RenderWindow = renWin; m_RenderWindow->Register(NULL); } else { itkWarningMacro(<< "Created mitkBaseRenderer without vtkRenderWindow present."); } m_Size[0] = 0; m_Size[1] = 0; //instances.insert( this ); //adding this BaseRenderer to the List of all BaseRenderer // TODO: INTERACTION_LEGACY m_RenderingManager->GetGlobalInteraction()->AddFocusElement(this); - m_BindDispatcherInteractor = mitk::BindDispatcherInteractor::New(); + m_BindDispatcherInteractor = new mitk::BindDispatcherInteractor(); WeakPointerProperty::Pointer rendererProp = WeakPointerProperty::New((itk::Object*) this); m_CurrentWorldGeometry2D = mitk::PlaneGeometry::New(); m_CurrentWorldGeometry2DData = mitk::Geometry2DData::New(); m_CurrentWorldGeometry2DData->SetGeometry2D(m_CurrentWorldGeometry2D); m_CurrentWorldGeometry2DNode = mitk::DataNode::New(); m_CurrentWorldGeometry2DNode->SetData(m_CurrentWorldGeometry2DData); m_CurrentWorldGeometry2DNode->GetPropertyList()->SetProperty("renderer", rendererProp); m_CurrentWorldGeometry2DNode->GetPropertyList()->SetProperty("layer", IntProperty::New(1000)); m_CurrentWorldGeometry2DNode->SetProperty("reslice.thickslices", mitk::ResliceMethodProperty::New()); m_CurrentWorldGeometry2DNode->SetProperty("reslice.thickslices.num", mitk::IntProperty::New(1)); m_CurrentWorldGeometry2DTransformTime = m_CurrentWorldGeometry2DNode->GetVtkTransform()->GetMTime(); m_DisplayGeometry = mitk::DisplayGeometry::New(); m_DisplayGeometry->SetWorldGeometry(m_CurrentWorldGeometry2D); m_DisplayGeometryData = mitk::Geometry2DData::New(); m_DisplayGeometryData->SetGeometry2D(m_DisplayGeometry); m_DisplayGeometryNode = mitk::DataNode::New(); m_DisplayGeometryNode->SetData(m_DisplayGeometryData); m_DisplayGeometryNode->GetPropertyList()->SetProperty("renderer", rendererProp); m_DisplayGeometryTransformTime = m_DisplayGeometryNode->GetVtkTransform()->GetMTime(); mitk::SliceNavigationController::Pointer sliceNavigationController = mitk::SliceNavigationController::New("navigation"); sliceNavigationController->SetRenderer(this); sliceNavigationController->ConnectGeometrySliceEvent(this); sliceNavigationController->ConnectGeometryUpdateEvent(this); sliceNavigationController->ConnectGeometryTimeEvent(this, false); m_SliceNavigationController = sliceNavigationController; m_CameraRotationController = mitk::CameraRotationController::New(); m_CameraRotationController->SetRenderWindow(m_RenderWindow); m_CameraRotationController->AcquireCamera(); //if TD Mouse Interaction is activated, then call TDMouseVtkCameraController instead of VtkInteractorCameraController #ifdef MITK_USE_TD_MOUSE m_CameraController = mitk::TDMouseVtkCameraController::New(); #else m_CameraController = mitk::CameraController::New(NULL); #endif m_VtkRenderer = vtkRenderer::New(); if (mitk::VtkLayerController::GetInstance(m_RenderWindow) == NULL) { mitk::VtkLayerController::AddInstance(m_RenderWindow, m_VtkRenderer); mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertSceneRenderer(m_VtkRenderer); } else mitk::VtkLayerController::GetInstance(m_RenderWindow)->InsertSceneRenderer(m_VtkRenderer); } mitk::BaseRenderer::~BaseRenderer() { if (m_VtkRenderer != NULL) { m_VtkRenderer->Delete(); m_VtkRenderer = NULL; } if (m_CameraController.IsNotNull()) m_CameraController->SetRenderer(NULL); m_RenderingManager->GetGlobalInteraction()->RemoveFocusElement(this); mitk::VtkLayerController::RemoveInstance(m_RenderWindow); RemoveAllLocalStorages(); m_DataStorage = NULL; + if (m_BindDispatcherInteractor != NULL) + { + delete m_BindDispatcherInteractor; + } + if (m_RenderWindow != NULL) { m_RenderWindow->Delete(); m_RenderWindow = NULL; } } void mitk::BaseRenderer::RemoveAllLocalStorages() { this->InvokeEvent(mitk::BaseRenderer::RendererResetEvent()); std::list::iterator it; for (it = m_RegisteredLocalStorageHandlers.begin(); it != m_RegisteredLocalStorageHandlers.end(); it++) (*it)->ClearLocalStorage(this, false); m_RegisteredLocalStorageHandlers.clear(); } void mitk::BaseRenderer::RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh) { m_RegisteredLocalStorageHandlers.push_back(lsh); } mitk::Dispatcher::Pointer mitk::BaseRenderer::GetDispatcher() { return m_BindDispatcherInteractor->GetDispatcher(); } mitk::Point3D mitk::BaseRenderer::Map2DRendererPositionTo3DWorldPosition(Point2D* mousePosition) const { Point2D p_mm; Point3D position; if (m_MapperID == 1) { GetDisplayGeometry()->ULDisplayToDisplay(*mousePosition, *mousePosition); GetDisplayGeometry()->DisplayToWorld(*mousePosition, p_mm); GetDisplayGeometry()->Map(p_mm, position); } else if (m_MapperID == 2) { GetDisplayGeometry()->ULDisplayToDisplay(*mousePosition, *mousePosition); PickWorldPoint(*mousePosition, position); } return position; } void mitk::BaseRenderer::UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh) { m_RegisteredLocalStorageHandlers.remove(lsh); } void mitk::BaseRenderer::SetDataStorage(DataStorage* storage) { if (storage != NULL) { m_DataStorage = storage; m_BindDispatcherInteractor->SetDataStorage(m_DataStorage); this->Modified(); } } const mitk::BaseRenderer::MapperSlotId mitk::BaseRenderer::defaultMapper = 1; void mitk::BaseRenderer::Paint() { } void mitk::BaseRenderer::Initialize() { } void mitk::BaseRenderer::Resize(int w, int h) { m_Size[0] = w; m_Size[1] = h; if (m_CameraController) m_CameraController->Resize(w, h); //(formerly problematic on windows: vtkSizeBug) GetDisplayGeometry()->SetSizeInDisplayUnits(w, h); } void mitk::BaseRenderer::InitRenderer(vtkRenderWindow* renderwindow) { if (m_RenderWindow != NULL) { m_RenderWindow->Delete(); } m_RenderWindow = renderwindow; if (m_RenderWindow != NULL) { m_RenderWindow->Register(NULL); } RemoveAllLocalStorages(); if (m_CameraController.IsNotNull()) { m_CameraController->SetRenderer(this); } //BUG (#1551) added settings for depth peeling m_RenderWindow->SetAlphaBitPlanes(1); m_VtkRenderer->SetUseDepthPeeling(m_DepthPeelingEnabled); m_VtkRenderer->SetMaximumNumberOfPeels(m_MaxNumberOfPeels); m_VtkRenderer->SetOcclusionRatio(0.1); } void mitk::BaseRenderer::InitSize(int w, int h) { m_Size[0] = w; m_Size[1] = h; GetDisplayGeometry()->SetSizeInDisplayUnits(w, h, false); GetDisplayGeometry()->Fit(); } void mitk::BaseRenderer::SetSlice(unsigned int slice) { if (m_Slice != slice) { m_Slice = slice; if (m_TimeSlicedWorldGeometry.IsNotNull()) { SlicedGeometry3D* slicedWorldGeometry = dynamic_cast(m_TimeSlicedWorldGeometry->GetGeometry3D(m_TimeStep)); if (slicedWorldGeometry != NULL) { if (m_Slice >= slicedWorldGeometry->GetSlices()) m_Slice = slicedWorldGeometry->GetSlices() - 1; SetCurrentWorldGeometry2D(slicedWorldGeometry->GetGeometry2D(m_Slice)); SetCurrentWorldGeometry(slicedWorldGeometry); } } else Modified(); } } void mitk::BaseRenderer::SetTimeStep(unsigned int timeStep) { if (m_TimeStep != timeStep) { m_TimeStep = timeStep; m_TimeStepUpdateTime.Modified(); if (m_TimeSlicedWorldGeometry.IsNotNull()) { if (m_TimeStep >= m_TimeSlicedWorldGeometry->GetTimeSteps()) m_TimeStep = m_TimeSlicedWorldGeometry->GetTimeSteps() - 1; SlicedGeometry3D* slicedWorldGeometry = dynamic_cast(m_TimeSlicedWorldGeometry->GetGeometry3D(m_TimeStep)); if (slicedWorldGeometry != NULL) { SetCurrentWorldGeometry2D(slicedWorldGeometry->GetGeometry2D(m_Slice)); SetCurrentWorldGeometry(slicedWorldGeometry); } } else Modified(); } } int mitk::BaseRenderer::GetTimeStep(const mitk::BaseData* data) const { if ((data == NULL) || (data->IsInitialized() == false)) { return -1; } return data->GetTimeSlicedGeometry()->MSToTimeStep(GetTime()); } mitk::ScalarType mitk::BaseRenderer::GetTime() const { if (m_TimeSlicedWorldGeometry.IsNull()) { return 0; } else { ScalarType timeInMS = m_TimeSlicedWorldGeometry->TimeStepToMS(GetTimeStep()); if (timeInMS == ScalarTypeNumericTraits::NonpositiveMin()) return 0; else return timeInMS; } } void mitk::BaseRenderer::SetWorldGeometry(mitk::Geometry3D* geometry) { itkDebugMacro("setting WorldGeometry to " << geometry); if (m_WorldGeometry != geometry) { if (geometry->GetBoundingBox()->GetDiagonalLength2() == 0) return; m_WorldGeometry = geometry; m_TimeSlicedWorldGeometry = dynamic_cast(geometry); SlicedGeometry3D* slicedWorldGeometry; if (m_TimeSlicedWorldGeometry.IsNotNull()) { itkDebugMacro("setting TimeSlicedWorldGeometry to " << m_TimeSlicedWorldGeometry); if (m_TimeStep >= m_TimeSlicedWorldGeometry->GetTimeSteps()) m_TimeStep = m_TimeSlicedWorldGeometry->GetTimeSteps() - 1; slicedWorldGeometry = dynamic_cast(m_TimeSlicedWorldGeometry->GetGeometry3D(m_TimeStep)); } else { slicedWorldGeometry = dynamic_cast(geometry); } Geometry2D::Pointer geometry2d; if (slicedWorldGeometry != NULL) { if (m_Slice >= slicedWorldGeometry->GetSlices() && (m_Slice != 0)) m_Slice = slicedWorldGeometry->GetSlices() - 1; geometry2d = slicedWorldGeometry->GetGeometry2D(m_Slice); if (geometry2d.IsNull()) { PlaneGeometry::Pointer plane = mitk::PlaneGeometry::New(); plane->InitializeStandardPlane(slicedWorldGeometry); geometry2d = plane; } SetCurrentWorldGeometry(slicedWorldGeometry); } else { geometry2d = dynamic_cast(geometry); if (geometry2d.IsNull()) { PlaneGeometry::Pointer plane = PlaneGeometry::New(); plane->InitializeStandardPlane(geometry); geometry2d = plane; } SetCurrentWorldGeometry(geometry); } SetCurrentWorldGeometry2D(geometry2d); // calls Modified() } if (m_CurrentWorldGeometry2D.IsNull()) itkWarningMacro("m_CurrentWorldGeometry2D is NULL"); } void mitk::BaseRenderer::SetDisplayGeometry(mitk::DisplayGeometry* geometry2d) { itkDebugMacro("setting DisplayGeometry to " << geometry2d); if (m_DisplayGeometry != geometry2d) { m_DisplayGeometry = geometry2d; m_DisplayGeometryData->SetGeometry2D(m_DisplayGeometry); m_DisplayGeometryUpdateTime.Modified(); Modified(); } } void mitk::BaseRenderer::SetCurrentWorldGeometry2D(mitk::Geometry2D* geometry2d) { if (m_CurrentWorldGeometry2D != geometry2d) { m_CurrentWorldGeometry2D = geometry2d; m_CurrentWorldGeometry2DData->SetGeometry2D(m_CurrentWorldGeometry2D); m_DisplayGeometry->SetWorldGeometry(m_CurrentWorldGeometry2D); m_CurrentWorldGeometry2DUpdateTime.Modified(); Modified(); } } void mitk::BaseRenderer::SendUpdateSlice() { m_DisplayGeometryUpdateTime.Modified(); m_CurrentWorldGeometry2DUpdateTime.Modified(); } void mitk::BaseRenderer::SetCurrentWorldGeometry(mitk::Geometry3D* geometry) { m_CurrentWorldGeometry = geometry; if (geometry == NULL) { m_Bounds[0] = 0; m_Bounds[1] = 0; m_Bounds[2] = 0; m_Bounds[3] = 0; m_Bounds[4] = 0; m_Bounds[5] = 0; m_EmptyWorldGeometry = true; return; } BoundingBox::Pointer boundingBox = m_CurrentWorldGeometry->CalculateBoundingBoxRelativeToTransform(NULL); const BoundingBox::BoundsArrayType& worldBounds = boundingBox->GetBounds(); m_Bounds[0] = worldBounds[0]; m_Bounds[1] = worldBounds[1]; m_Bounds[2] = worldBounds[2]; m_Bounds[3] = worldBounds[3]; m_Bounds[4] = worldBounds[4]; m_Bounds[5] = worldBounds[5]; if (boundingBox->GetDiagonalLength2() <= mitk::eps) m_EmptyWorldGeometry = true; else m_EmptyWorldGeometry = false; } void mitk::BaseRenderer::SetGeometry(const itk::EventObject & geometrySendEvent) { const SliceNavigationController::GeometrySendEvent* sendEvent = dynamic_cast(&geometrySendEvent); assert(sendEvent!=NULL); SetWorldGeometry(sendEvent->GetTimeSlicedGeometry()); } void mitk::BaseRenderer::UpdateGeometry(const itk::EventObject & geometryUpdateEvent) { const SliceNavigationController::GeometryUpdateEvent* updateEvent = dynamic_cast(&geometryUpdateEvent); if (updateEvent == NULL) return; if (m_CurrentWorldGeometry.IsNotNull()) { SlicedGeometry3D* slicedWorldGeometry = dynamic_cast(m_CurrentWorldGeometry.GetPointer()); if (slicedWorldGeometry) { Geometry2D* geometry2D = slicedWorldGeometry->GetGeometry2D(m_Slice); SetCurrentWorldGeometry2D(geometry2D); // calls Modified() } } } void mitk::BaseRenderer::SetGeometrySlice(const itk::EventObject & geometrySliceEvent) { const SliceNavigationController::GeometrySliceEvent* sliceEvent = dynamic_cast(&geometrySliceEvent); assert(sliceEvent!=NULL); SetSlice(sliceEvent->GetPos()); } void mitk::BaseRenderer::SetGeometryTime(const itk::EventObject & geometryTimeEvent) { const SliceNavigationController::GeometryTimeEvent * timeEvent = dynamic_cast(&geometryTimeEvent); assert(timeEvent!=NULL); SetTimeStep(timeEvent->GetPos()); } const double* mitk::BaseRenderer::GetBounds() const { return m_Bounds; } void mitk::BaseRenderer::MousePressEvent(mitk::MouseEvent *me) { //set the Focus on the renderer /*bool success =*/m_RenderingManager->GetGlobalInteraction()->SetFocus(this); /* if (! success) mitk::StatusBar::GetInstance()->DisplayText("Warning! from mitkBaseRenderer.cpp: Couldn't focus this BaseRenderer!"); */ //if (m_CameraController) //{ // if(me->GetButtonState()!=512) // provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine // m_CameraController->MousePressEvent(me); //} if (m_MapperID == 1) { Point2D p(me->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID > 1) //==2 for 3D and ==5 for stencil { Point2D p(me->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); me->SetDisplayPosition(p); mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::MouseReleaseEvent(mitk::MouseEvent *me) { //if (m_CameraController) //{ // if(me->GetButtonState()!=512) // provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine // m_CameraController->MouseReleaseEvent(me); //} if (m_MapperID == 1) { Point2D p(me->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(me->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); me->SetDisplayPosition(p); mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::MouseMoveEvent(mitk::MouseEvent *me) { //if (m_CameraController) //{ // if((me->GetButtonState()<=512) || (me->GetButtonState()>=516))// provisorisch: Ctrl nicht durchlassen. Bald wird aus m_CameraController eine StateMachine // m_CameraController->MouseMoveEvent(me); //} if (m_MapperID == 1) { Point2D p(me->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, me->GetType(), me->GetButton(), me->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(me->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); me->SetDisplayPosition(p); mitk::EventMapper::MapEvent(me, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::PickWorldPoint(const mitk::Point2D& displayPoint, mitk::Point3D& worldPoint) const { mitk::Point2D worldPoint2D; GetDisplayGeometry()->DisplayToWorld(displayPoint, worldPoint2D); GetDisplayGeometry()->Map(worldPoint2D, worldPoint); } void mitk::BaseRenderer::WheelEvent(mitk::WheelEvent * we) { if (m_MapperID == 1) { Point2D p(we->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::PositionEvent event(this, we->GetType(), we->GetButton(), we->GetButtonState(), mitk::Key_unknown, p, position); mitk::EventMapper::MapEvent(we, m_RenderingManager->GetGlobalInteraction()); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(we->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); we->SetDisplayPosition(p); mitk::EventMapper::MapEvent(we, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::KeyPressEvent(mitk::KeyEvent *ke) { if (m_MapperID == 1) { Point2D p(ke->GetDisplayPosition()); Point2D p_mm; Point3D position; GetDisplayGeometry()->ULDisplayToDisplay(p, p); GetDisplayGeometry()->DisplayToWorld(p, p_mm); GetDisplayGeometry()->Map(p_mm, position); mitk::KeyEvent event(this, ke->GetType(), ke->GetButton(), ke->GetButtonState(), ke->GetKey(), ke->GetText(), p); mitk::EventMapper::MapEvent(&event, m_RenderingManager->GetGlobalInteraction()); } else if (m_MapperID == 2) { Point2D p(ke->GetDisplayPosition()); GetDisplayGeometry()->ULDisplayToDisplay(p, p); ke->SetDisplayPosition(p); mitk::EventMapper::MapEvent(ke, m_RenderingManager->GetGlobalInteraction()); } } void mitk::BaseRenderer::DrawOverlayMouse(mitk::Point2D& itkNotUsed(p2d)) { MITK_INFO<<"BaseRenderer::DrawOverlayMouse()- should be inconcret implementation OpenGLRenderer."<RequestUpdate(this->m_RenderWindow); } void mitk::BaseRenderer::ForceImmediateUpdate() { m_RenderingManager->ForceImmediateUpdate(this->m_RenderWindow); } unsigned int mitk::BaseRenderer::GetNumberOfVisibleLODEnabledMappers() const { return m_NumberOfVisibleLODEnabledMappers; } mitk::RenderingManager* mitk::BaseRenderer::GetRenderingManager() const { return m_RenderingManager.GetPointer(); } /*! Sets the new Navigation controller */ void mitk::BaseRenderer::SetSliceNavigationController(mitk::SliceNavigationController *SlicenavigationController) { if (SlicenavigationController == NULL) return; //disconnect old from globalinteraction m_RenderingManager->GetGlobalInteraction()->RemoveListener(SlicenavigationController); //copy worldgeometry SlicenavigationController->SetInputWorldGeometry(SlicenavigationController->GetCreatedWorldGeometry()); SlicenavigationController->Update(); //set new m_SliceNavigationController = SlicenavigationController; m_SliceNavigationController->SetRenderer(this); if (m_SliceNavigationController.IsNotNull()) { m_SliceNavigationController->ConnectGeometrySliceEvent(this); m_SliceNavigationController->ConnectGeometryUpdateEvent(this); m_SliceNavigationController->ConnectGeometryTimeEvent(this, false); } } /*! Sets the new camera controller and deletes the vtkRenderWindowInteractor in case of the VTKInteractorCameraController */ void mitk::BaseRenderer::SetCameraController(CameraController* cameraController) { mitk::VtkInteractorCameraController::Pointer vtkInteractorCameraController = dynamic_cast(cameraController); if (vtkInteractorCameraController.IsNotNull()) MITK_INFO<<"!!!WARNING!!!: RenderWindow interaction events are no longer handled via CameraController (See Bug #954)."<SetRenderer(NULL); m_CameraController = NULL; m_CameraController = cameraController; m_CameraController->SetRenderer(this); } void mitk::BaseRenderer::PrintSelf(std::ostream& os, itk::Indent indent) const { os << indent << " MapperID: " << m_MapperID << std::endl; os << indent << " Slice: " << m_Slice << std::endl; os << indent << " TimeStep: " << m_TimeStep << std::endl; os << indent << " WorldGeometry: "; if (m_WorldGeometry.IsNull()) os << "NULL" << std::endl; else m_WorldGeometry->Print(os, indent); os << indent << " CurrentWorldGeometry2D: "; if (m_CurrentWorldGeometry2D.IsNull()) os << "NULL" << std::endl; else m_CurrentWorldGeometry2D->Print(os, indent); os << indent << " CurrentWorldGeometry2DUpdateTime: " << m_CurrentWorldGeometry2DUpdateTime << std::endl; os << indent << " CurrentWorldGeometry2DTransformTime: " << m_CurrentWorldGeometry2DTransformTime << std::endl; os << indent << " DisplayGeometry: "; if (m_DisplayGeometry.IsNull()) os << "NULL" << std::endl; else m_DisplayGeometry->Print(os, indent); os << indent << " DisplayGeometryTransformTime: " << m_DisplayGeometryTransformTime << std::endl; Superclass::PrintSelf(os, indent); } void mitk::BaseRenderer::SetDepthPeelingEnabled(bool enabled) { m_DepthPeelingEnabled = enabled; m_VtkRenderer->SetUseDepthPeeling(enabled); } void mitk::BaseRenderer::SetMaxNumberOfPeels(int maxNumber) { m_MaxNumberOfPeels = maxNumber; m_VtkRenderer->SetMaximumNumberOfPeels(maxNumber); } diff --git a/Core/Code/Rendering/mitkBaseRenderer.h b/Core/Code/Rendering/mitkBaseRenderer.h index 33ba6ea9d3..db2f18f4ba 100644 --- a/Core/Code/Rendering/mitkBaseRenderer.h +++ b/Core/Code/Rendering/mitkBaseRenderer.h @@ -1,633 +1,611 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 #define BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 #include "mitkDataStorage.h" #include "mitkGeometry2D.h" #include "mitkTimeSlicedGeometry.h" #include "mitkDisplayGeometry.h" #include "mitkGeometry2DData.h" #include "mitkCameraController.h" #include "mitkDisplayPositionEvent.h" #include "mitkWheelEvent.h" //#include "mitkMapper.h" #include "mitkSliceNavigationController.h" #include "mitkCameraController.h" #include "mitkCameraRotationController.h" #include "mitkBindDispatcherInteractor.h" #include "mitkDispatcher.h" #include #include #include #include namespace mitk { class NavigationController; class SliceNavigationController; class CameraRotationController; class CameraController; class DataStorage; class Mapper; class BaseLocalStorageHandler; //##Documentation //## @brief Organizes the rendering process //## //## Organizes the rendering process. A Renderer contains a reference to a //## DataStorage and asks the mappers of the data objects to render //## the data into the renderwindow it is associated to. //## //## \#Render() checks if rendering is currently allowed by calling //## RenderWindow::PrepareRendering(). Initialization of a rendering context //## can also be performed in this method. //## //## The actual rendering code has been moved to \#Repaint() //## Both \#Repaint() and \#Update() are declared protected now. //## //## Note: Separation of the Repaint and Update processes (rendering vs //## creating a vtk prop tree) still needs to be worked on. The whole //## rendering process also should be reworked to use VTK based classes for //## both 2D and 3D rendering. //## @ingroup Renderer class MITK_CORE_EXPORT BaseRenderer: public itk::Object { public: typedef std::map BaseRendererMapType; static BaseRendererMapType baseRendererMap; static BaseRenderer* GetInstance(vtkRenderWindow * renWin); static void AddInstance(vtkRenderWindow* renWin, BaseRenderer* baseRenderer); static void RemoveInstance(vtkRenderWindow* renWin); static BaseRenderer* GetByName(const std::string& name); static vtkRenderWindow* GetRenderWindowByName(const std::string& name); #pragma GCC visibility push(default) itkEventMacro( RendererResetEvent, itk::AnyEvent ); #pragma GCC visibility pop /** Standard class typedefs. */ mitkClassMacro(BaseRenderer, itk::Object); BaseRenderer(const char* name = NULL, vtkRenderWindow * renWin = NULL, mitk::RenderingManager* rm = NULL); //##Documentation //## @brief MapperSlotId defines which kind of mapper (e.g., 2D or 3D) shoud be used. typedef int MapperSlotId; enum StandardMapperSlot { Standard2D = 1, Standard3D = 2 }; virtual void SetDataStorage(DataStorage* storage); ///< set the datastorage that will be used for rendering //##Documentation //## return the DataStorage that is used for rendering virtual DataStorage::Pointer GetDataStorage() const { return m_DataStorage.GetPointer(); - }; + } //##Documentation //## @brief Access the RenderWindow into which this renderer renders. vtkRenderWindow* GetRenderWindow() const { return m_RenderWindow; } vtkRenderer* GetVtkRenderer() const { return m_VtkRenderer; } //##Documentation //## @brief Returns the Dispatcher which handles Events for this BaseRenderer Dispatcher::Pointer GetDispatcher(); //##Documentation //## @brief Default mapper id to use. static const MapperSlotId defaultMapper; //##Documentation //## @brief Do the rendering and flush the result. virtual void Paint(); //##Documentation //## @brief Initialize the RenderWindow. Should only be called from RenderWindow. virtual void Initialize(); //##Documentation //## @brief Called to inform the renderer that the RenderWindow has been resized. virtual void Resize(int w, int h); //##Documentation //## @brief Initialize the renderer with a RenderWindow (@a renderwindow). virtual void InitRenderer(vtkRenderWindow* renderwindow); //##Documentation //## @brief Set the initial size. Called by RenderWindow after it has become //## visible for the first time. virtual void InitSize(int w, int h); //##Documentation //## @brief Draws a point on the widget. //## Should be used during conferences to show the position of the remote mouse virtual void DrawOverlayMouse(Point2D& p2d); //##Documentation //## @brief Set/Get the WorldGeometry (m_WorldGeometry) for 3D and 2D rendering, that describing the //## (maximal) area to be rendered. //## //## Depending of the type of the passed Geometry3D more or less information can be extracted: //## \li if it is a Geometry2D (which is a sub-class of Geometry3D), m_CurrentWorldGeometry2D is //## also set to point to it. m_TimeSlicedWorldGeometry is set to NULL. //## \li if it is a TimeSlicedGeometry, m_TimeSlicedWorldGeometry is also set to point to it. //## If m_TimeSlicedWorldGeometry contains instances of SlicedGeometry3D, m_CurrentWorldGeometry2D is set to //## one of geometries stored in the SlicedGeometry3D according to the value of m_Slice; otherwise //## a PlaneGeometry describing the top of the bounding-box of the Geometry3D is set as the //## m_CurrentWorldGeometry2D. //## \li otherwise a PlaneGeometry describing the top of the bounding-box of the Geometry3D //## is set as the m_CurrentWorldGeometry2D. m_TimeSlicedWorldGeometry is set to NULL. //## @todo add calculation of PlaneGeometry describing the top of the bounding-box of the Geometry3D //## when the passed Geometry3D is not sliced. //## \sa m_WorldGeometry //## \sa m_TimeSlicedWorldGeometry //## \sa m_CurrentWorldGeometry2D virtual void SetWorldGeometry(Geometry3D* geometry); itkGetConstObjectMacro(WorldGeometry, Geometry3D) - ; //##Documentation //## @brief Get the current 3D-worldgeometry (m_CurrentWorldGeometry) used for 3D-rendering itkGetConstObjectMacro(CurrentWorldGeometry, Geometry3D) - ; //##Documentation //## @brief Get the current 2D-worldgeometry (m_CurrentWorldGeometry2D) used for 2D-rendering itkGetConstObjectMacro(CurrentWorldGeometry2D, Geometry2D) - ; //##Documentation //## Calculates the bounds of the DataStorage (if it contains any valid data), //## creates a geometry from these bounds and sets it as world geometry of the renderer. //## //## Call this method to re-initialize the renderer to the current DataStorage //## (e.g. after loading an additional dataset), to ensure that the view is //## aligned correctly. //## \warn This is not implemented yet. virtual bool SetWorldGeometryToDataStorageBounds() { return false; } //##Documentation //## @brief Set/Get the DisplayGeometry (for 2D rendering) //## //## The DisplayGeometry describes which part of the Geometry2D m_CurrentWorldGeometry2D //## is displayed. virtual void SetDisplayGeometry(DisplayGeometry* geometry2d); itkGetConstObjectMacro(DisplayGeometry, DisplayGeometry) - ; - itkGetObjectMacro(DisplayGeometry, DisplayGeometry) - ; //##Documentation //## @brief Set/Get m_Slice which defines together with m_TimeStep the 2D geometry //## stored in m_TimeSlicedWorldGeometry used as m_CurrentWorldGeometry2D //## //## \sa m_Slice virtual void SetSlice(unsigned int slice); itkGetConstMacro(Slice, unsigned int) - ; //##Documentation //## @brief Set/Get m_TimeStep which defines together with m_Slice the 2D geometry //## stored in m_TimeSlicedWorldGeometry used as m_CurrentWorldGeometry2D //## //## \sa m_TimeStep virtual void SetTimeStep(unsigned int timeStep); itkGetConstMacro(TimeStep, unsigned int) - ; //##Documentation //## @brief Get the time-step of a BaseData object which //## exists at the time of the currently displayed content //## //## Returns -1 or mitk::BaseData::m_TimeSteps if there //## is no data at the current time. //## \sa GetTimeStep, m_TimeStep int GetTimeStep(const BaseData* data) const; //##Documentation //## @brief Get the time in ms of the currently displayed content //## //## \sa GetTimeStep, m_TimeStep ScalarType GetTime() const; //##Documentation //## @brief SetWorldGeometry is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometrySendEvent virtual void SetGeometry(const itk::EventObject & geometrySliceEvent); //##Documentation //## @brief UpdateWorldGeometry is called to re-read the 2D geometry from the //## slice navigation controller virtual void UpdateGeometry(const itk::EventObject & geometrySliceEvent); //##Documentation //## @brief SetSlice is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometrySliceEvent virtual void SetGeometrySlice(const itk::EventObject & geometrySliceEvent); //##Documentation //## @brief SetTimeStep is called according to the geometrySliceEvent, //## which is supposed to be a SliceNavigationController::GeometryTimeEvent virtual void SetGeometryTime(const itk::EventObject & geometryTimeEvent); //##Documentation //## @brief Get a data object containing the DisplayGeometry (for 2D rendering) itkGetObjectMacro(DisplayGeometryData, Geometry2DData) - ; //##Documentation //## @brief Get a data object containing the WorldGeometry (for 2D rendering) itkGetObjectMacro(WorldGeometryData, Geometry2DData) - ; //##Documentation //## @brief Get a DataNode pointing to a data object containing the WorldGeometry (3D and 2D rendering) itkGetObjectMacro(WorldGeometryNode, DataNode) - ; //##Documentation //## @brief Get a DataNode pointing to a data object containing the DisplayGeometry (for 2D rendering) itkGetObjectMacro(DisplayGeometryNode, DataNode) - ; //##Documentation //## @brief Get a DataNode pointing to a data object containing the current 2D-worldgeometry m_CurrentWorldGeometry2D (for 2D rendering) itkGetObjectMacro(CurrentWorldGeometry2DNode, DataNode) - ; //##Documentation //## @brief Sets timestamp of CurrentWorldGeometry2D and DisplayGeometry and forces so reslicing in that renderwindow void SendUpdateSlice(); //##Documentation //## @brief Get timestamp of last call of SetCurrentWorldGeometry2D unsigned long GetCurrentWorldGeometry2DUpdateTime() { return m_CurrentWorldGeometry2DUpdateTime; } - ; //##Documentation //## @brief Get timestamp of last call of SetDisplayGeometry unsigned long GetDisplayGeometryUpdateTime() { return m_CurrentWorldGeometry2DUpdateTime; } - ; //##Documentation //## @brief Get timestamp of last change of current TimeStep unsigned long GetTimeStepUpdateTime() { return m_TimeStepUpdateTime; } - ; //##Documentation //## @brief Perform a picking: find the x,y,z world coordinate of a //## display x,y coordinate. //## @warning Has to be overwritten in subclasses for the 3D-case. //## //## Implemented here only for 2D-rendering by using //## m_DisplayGeometry virtual void PickWorldPoint(const Point2D& diplayPosition, Point3D& worldPosition) const; /** \brief Determines the object (mitk::DataNode) closest to the current * position by means of picking * * \warning Implementation currently empty for 2D rendering; intended to be * implemented for 3D renderers */ virtual DataNode* PickObject(const Point2D& /*displayPosition*/, Point3D& /*worldPosition*/) const { return NULL; } - ; //##Documentation //## @brief Get the MapperSlotId to use. itkGetMacro(MapperID, MapperSlotId) - ;itkGetConstMacro(MapperID, MapperSlotId) - ; + itkGetConstMacro(MapperID, MapperSlotId) + //##Documentation //## @brief Set the MapperSlotId to use. itkSetMacro(MapperID, MapperSlotId) - ; //##Documentation //## @brief Has the renderer the focus? itkGetMacro(Focused, bool) - ; //##Documentation //## @brief Tell the renderer that it is focused. The caller is responsible for focus management, //## not the renderer itself. itkSetMacro(Focused, bool) - ; //##Documentation //## @brief Sets whether depth peeling is enabled or not void SetDepthPeelingEnabled(bool enabled); //##Documentation //## @brief Sets maximal number of peels void SetMaxNumberOfPeels(int maxNumber); itkGetMacro(Size, int*) - ; void SetSliceNavigationController(SliceNavigationController* SlicenavigationController); - void SetCameraController(CameraController* cameraController);itkGetObjectMacro(CameraController, CameraController) - ;itkGetObjectMacro(SliceNavigationController, SliceNavigationController) - ;itkGetObjectMacro(CameraRotationController, CameraRotationController) - ; + void SetCameraController(CameraController* cameraController); + itkGetObjectMacro(CameraController, CameraController) + itkGetObjectMacro(SliceNavigationController, SliceNavigationController) + itkGetObjectMacro(CameraRotationController, CameraRotationController) itkGetMacro(EmptyWorldGeometry, bool) - ; //##Documentation //## @brief Mouse event dispatchers //## @note for internal use only. preliminary. virtual void MousePressEvent(MouseEvent*); //##Documentation //## @brief Mouse event dispatchers //## @note for internal use only. preliminary. virtual void MouseReleaseEvent(MouseEvent*); //##Documentation //## @brief Mouse event dispatchers //## @note for internal use only. preliminary. virtual void MouseMoveEvent(MouseEvent*); //##Documentation //## @brief Wheel event dispatcher //## @note for internal use only. preliminary. virtual void WheelEvent(mitk::WheelEvent* we); //##Documentation //## @brief Key event dispatcher //## @note for internal use only. preliminary. virtual void KeyPressEvent(KeyEvent*); //##Documentation //## @brief get the name of the Renderer //## @note const char * GetName() const { return m_Name.c_str(); } //##Documentation //## @brief get the x_size of the RendererWindow //## @note int GetSizeX() const { return m_Size[0]; } //##Documentation //## @brief get the y_size of the RendererWindow //## @note int GetSizeY() const { return m_Size[1]; } const double* GetBounds() const; void RequestUpdate(); void ForceImmediateUpdate(); /** Returns number of mappers which are visible and have level-of-detail * rendering enabled */ unsigned int GetNumberOfVisibleLODEnabledMappers() const; ///** //* \brief Setter for the RenderingManager that handles this instance of BaseRenderer //*/ //void SetRenderingManager( mitk::RenderingManager* ); /** * \brief Getter for the RenderingManager that handles this instance of BaseRenderer */ virtual mitk::RenderingManager* GetRenderingManager() const; /** * \brief Provides (1) world coordinates for a given mouse position and (2) * translates mousePosition to Display coordinates */ virtual Point3D Map2DRendererPositionTo3DWorldPosition(Point2D* mousePosition) const; protected: virtual ~BaseRenderer(); //##Documentation //## @brief Call update of all mappers. To be implemented in subclasses. virtual void Update() = 0; vtkRenderWindow* m_RenderWindow; vtkRenderer* m_VtkRenderer; //##Documentation //## @brief MapperSlotId to use. Defines which kind of mapper (e.g., 2D or 3D) shoud be used. MapperSlotId m_MapperID; //##Documentation //## @brief The DataStorage that is used for rendering. DataStorage::Pointer m_DataStorage; //##Documentation //## @brief The RenderingManager that manages this instance RenderingManager::Pointer m_RenderingManager; //##Documentation //## @brief Timestamp of last call of Update(). unsigned long m_LastUpdateTime; //##Documentation //## @brief CameraController for 3D rendering //## @note preliminary. CameraController::Pointer m_CameraController; SliceNavigationController::Pointer m_SliceNavigationController; CameraRotationController::Pointer m_CameraRotationController; //##Documentation //## @brief Size of the RenderWindow. int m_Size[2]; //##Documentation //## @brief Contains whether the renderer that it is focused. The caller of //## SetFocused is responsible for focus management, not the renderer itself. //## is doubled because of mitk::FocusManager in GlobalInteraction!!! (ingmar) bool m_Focused; //##Documentation //## @brief Sets m_CurrentWorldGeometry2D virtual void SetCurrentWorldGeometry2D(Geometry2D* geometry2d); //##Documentation //## @brief Sets m_CurrentWorldGeometry virtual void SetCurrentWorldGeometry(Geometry3D* geometry); private: //##Documentation //## Pointer to the worldgeometry, describing the maximal area to be rendered //## (3D as well as 2D). //## It is const, since we are not allowed to change it (it may be taken //## directly from the geometry of an image-slice and thus it would be //## very strange when suddenly the image-slice changes its geometry). //## \sa SetWorldGeometry Geometry3D::Pointer m_WorldGeometry; //##Documentation //## m_TimeSlicedWorldGeometry is set by SetWorldGeometry if the passed Geometry3D is a //## TimeSlicedGeometry (or a sub-class of it). If it contains instances of SlicedGeometry3D, //## m_Slice and m_TimeStep (set via SetSlice and SetTimeStep, respectively) define //## which 2D geometry stored in m_TimeSlicedWorldGeometry (if available) //## is used as m_CurrentWorldGeometry2D. //## \sa m_CurrentWorldGeometry2D TimeSlicedGeometry::Pointer m_TimeSlicedWorldGeometry; //##Documentation //## Pointer to the current 3D-worldgeometry. Geometry3D::Pointer m_CurrentWorldGeometry; //##Documentation //## Pointer to the current 2D-worldgeometry. The 2D-worldgeometry //## describes the maximal area (2D manifold) to be rendered in case we //## are doing 2D-rendering. More precisely, a subpart of this according //## to m_DisplayGeometry is displayed. //## It is const, since we are not allowed to change it (it may be taken //## directly from the geometry of an image-slice and thus it would be //## very strange when suddenly the image-slice changes its geometry). Geometry2D::Pointer m_CurrentWorldGeometry2D; //##Documentation //## Pointer to the displaygeometry. The displaygeometry describes the //## geometry of the \em visible area in the window controlled by the renderer //## in case we are doing 2D-rendering. //## It is const, since we are not allowed to change it. DisplayGeometry::Pointer m_DisplayGeometry; //##Documentation //## Defines together with m_Slice which 2D geometry stored in m_TimeSlicedWorldGeometry //## is used as m_CurrentWorldGeometry2D: m_TimeSlicedWorldGeometry->GetGeometry2D(m_Slice, m_TimeStep). //## \sa m_TimeSlicedWorldGeometry unsigned int m_Slice; //##Documentation //## Defines together with m_TimeStep which 2D geometry stored in m_TimeSlicedWorldGeometry //## is used as m_CurrentWorldGeometry2D: m_TimeSlicedWorldGeometry->GetGeometry2D(m_Slice, m_TimeStep). //## \sa m_TimeSlicedWorldGeometry unsigned int m_TimeStep; //##Documentation //## @brief timestamp of last call of SetWorldGeometry itk::TimeStamp m_CurrentWorldGeometry2DUpdateTime; //##Documentation //## @brief timestamp of last call of SetDisplayGeometry itk::TimeStamp m_DisplayGeometryUpdateTime; //##Documentation //## @brief timestamp of last change of the current time step itk::TimeStamp m_TimeStepUpdateTime; //##Documentation //## @brief Helper class which establishes connection between Interactors and Dispatcher via a common DataStorage. - BindDispatcherInteractor::Pointer m_BindDispatcherInteractor; + BindDispatcherInteractor* m_BindDispatcherInteractor; protected: virtual void PrintSelf(std::ostream& os, itk::Indent indent) const; //##Documentation //## Data object containing the m_WorldGeometry defined above. Geometry2DData::Pointer m_WorldGeometryData; //##Documentation //## Data object containing the m_DisplayGeometry defined above. Geometry2DData::Pointer m_DisplayGeometryData; //##Documentation //## Data object containing the m_CurrentWorldGeometry2D defined above. Geometry2DData::Pointer m_CurrentWorldGeometry2DData; //##Documentation //## DataNode objects containing the m_WorldGeometryData defined above. DataNode::Pointer m_WorldGeometryNode; //##Documentation //## DataNode objects containing the m_DisplayGeometryData defined above. DataNode::Pointer m_DisplayGeometryNode; //##Documentation //## DataNode objects containing the m_CurrentWorldGeometry2DData defined above. DataNode::Pointer m_CurrentWorldGeometry2DNode; //##Documentation //## @brief test only unsigned long m_DisplayGeometryTransformTime; //##Documentation //## @brief test only unsigned long m_CurrentWorldGeometry2DTransformTime; std::string m_Name; double m_Bounds[6]; bool m_EmptyWorldGeometry; bool m_DepthPeelingEnabled; int m_MaxNumberOfPeels; typedef std::set LODEnabledMappersType; /** Number of mappers which are visible and have level-of-detail * rendering enabled */ unsigned int m_NumberOfVisibleLODEnabledMappers; // Local Storage Handling for mappers protected: std::list m_RegisteredLocalStorageHandlers; public: void RemoveAllLocalStorages(); void RegisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh); void UnregisterLocalStorageHandler(mitk::BaseLocalStorageHandler *lsh); }; } // namespace mitk #endif /* BASERENDERER_H_HEADER_INCLUDED_C1CCA0F4 */ diff --git a/Core/Code/Rendering/mitkGLMapper2D.cpp b/Core/Code/Rendering/mitkGLMapper.cpp similarity index 56% rename from Core/Code/Rendering/mitkGLMapper2D.cpp rename to Core/Code/Rendering/mitkGLMapper.cpp index 8c02c43300..e383a306d4 100644 --- a/Core/Code/Rendering/mitkGLMapper2D.cpp +++ b/Core/Code/Rendering/mitkGLMapper.cpp @@ -1,61 +1,56 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkGL.h" -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" -mitk::GLMapper2D::GLMapper2D() -{ +mitk::GLMapper::GLMapper() +{ } - -mitk::GLMapper2D::~GLMapper2D() +mitk::GLMapper::~GLMapper() { } -void mitk::GLMapper2D::MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer) +void mitk::GLMapper::MitkRender(mitk::BaseRenderer* renderer, mitk::VtkPropRenderer::RenderType /* type */) { - if(IsVisible(renderer)==false) - return; + bool visible = true; - Paint(renderer); -} -void mitk::GLMapper2D::MitkRenderTranslucentGeometry(mitk::BaseRenderer* /*renderer*/) -{ + GetDataNode()->GetVisibility(visible, renderer, "visible"); -} -void mitk::GLMapper2D::MitkRenderOverlay(mitk::BaseRenderer* /*renderer*/) -{ + if(!visible) + return; + Paint(renderer); } -void mitk::GLMapper2D::MitkRenderVolumetricGeometry(mitk::BaseRenderer* /*renderer*/) +bool mitk::GLMapper::IsVtkBased() const { - + return false; } -void mitk::GLMapper2D::ApplyProperties(mitk::BaseRenderer* renderer) +void mitk::GLMapper::ApplyColorAndOpacityProperties(mitk::BaseRenderer* renderer, vtkActor* /*actor*/) { float rgba[4]={1.0f,1.0f,1.0f,1.0f}; // check for color prop and use it for rendering if it exists - GetColor(rgba, renderer); + GetDataNode()->GetColor(rgba, renderer, "color"); // check for opacity prop and use it for rendering if it exists - GetOpacity(rgba[3], renderer); + GetDataNode()->GetOpacity(rgba[3], renderer, "opacity"); glColor4fv(rgba); } diff --git a/Core/Code/Rendering/mitkGLMapper.h b/Core/Code/Rendering/mitkGLMapper.h new file mode 100644 index 0000000000..3f9fa755cd --- /dev/null +++ b/Core/Code/Rendering/mitkGLMapper.h @@ -0,0 +1,102 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKGLMAPPER_H_HEADER_INCLUDED_C197C872 +#define MITKGLMAPPER_H_HEADER_INCLUDED_C197C872 + +#include +#include "mitkMapper.h" +#include "mitkBaseRenderer.h" +#include "mitkVtkPropRenderer.h" + +namespace mitk { + + +/** \brief Base class of all OpenGL-based mappers. +* +* Those must implement the abstract method Paint(BaseRenderer), which is called by +* method MitkRender(). +* The Paint() method should be used to paint into a renderer via OpenGL-drawing commands. +* The OpenGL context matrices (GL_MODELVIEWMATRIX/GL_PROJECTIONMATRIX) are preinitialized by +* the mitkVtkPropRenderer so that the origin of the 2D-coordinate system of the 2D render +* window is located in the lower left corner and has the width and height in display pixels +* of the respective renderwindow. The x-axis is horizontally oriented, while the y-axis is +* vertically oriented. The drawing commands are directly interpreted as display coordinates. +* ApplyColorAndOpacity() can be used in the subclasses to apply color and opacity properties +* read from the PropertyList. +* +* \ingroup Mapper +*/ +class MITK_CORE_EXPORT GLMapper : public Mapper +{ + public: + /** \brief Do the painting into the \a renderer */ + virtual void Paint(mitk::BaseRenderer *renderer) = 0; + + /** \brief Apply color and opacity properties read from the PropertyList + * @deprecated Use ApplyColorAndOpacityProperties(...) instead + */ + DEPRECATED(inline virtual void ApplyProperties(mitk::BaseRenderer* renderer) + { + ApplyColorAndOpacityProperties(renderer); + }); + + /** \brief Apply color and opacity properties read from the PropertyList. + * The actor is not used in the GLMappers. Called by mapper subclasses. + */ + virtual void ApplyColorAndOpacityProperties(mitk::BaseRenderer* renderer, vtkActor* actor = NULL); + + + /** \brief Checks visibility and calls the paint method + * + * Note: The enumeration is disregarded, since OpenGL rendering only needs a + * single render pass. + */ + void MitkRender(mitk::BaseRenderer* renderer, mitk::VtkPropRenderer::RenderType type); + + /** \brief Returns whether this is a vtk-based mapper + * \return false, since all mappers deriving from this class are OpenGL mappers + * @deprecated All mappers of superclass VTKMapper are vtk based, use a dynamic_cast instead + */ + DEPRECATED( virtual bool IsVtkBased() const ); + + /** \brief Returns whether this mapper allows picking in the renderwindow + virtual bool IsPickable() const { return false; }*/ + + protected: + + /** constructor */ + GLMapper(); + + /** virtual destructor in order to derive from this class */ + virtual ~GLMapper(); + + private: + + /** copy constructor */ + GLMapper( const GLMapper &); + + /** assignment operator */ + GLMapper & operator=(const GLMapper &); + +}; + +} // namespace mitk + + + +#endif /* MITKGLMAPPER2D_H_HEADER_INCLUDED_C197C872 */ diff --git a/Core/Code/Rendering/mitkGLMapper2D.h b/Core/Code/Rendering/mitkGLMapper2D.h index 07cfe071cc..d332e5ee60 100644 --- a/Core/Code/Rendering/mitkGLMapper2D.h +++ b/Core/Code/Rendering/mitkGLMapper2D.h @@ -1,66 +1,35 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKGLMAPPER2D_H_HEADER_INCLUDED_C197C872 #define MITKGLMAPPER2D_H_HEADER_INCLUDED_C197C872 -#include -#include "mitkMapper2D.h" -#include "mitkBaseRenderer.h" +#include "mitkGLMapper.h" namespace mitk { -//##Documentation -//## @brief Base class of all OpenGL-based 2D-Mappers -//## -//## Those must implement the abstract method Paint(BaseRenderer). -//## @ingroup Mapper -class MITK_CORE_EXPORT GLMapper2D : public Mapper2D -{ - public: - //##Documentation - //## @brief Do the painting into the @a renderer - virtual void Paint(mitk::BaseRenderer *renderer) = 0; - - //##Documentation - //## @brief Apply color and opacity read from the PropertyList - virtual void ApplyProperties(mitk::BaseRenderer* renderer); - - void MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer); - void MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer); - void MitkRenderOverlay(mitk::BaseRenderer* renderer); - void MitkRenderVolumetricGeometry(mitk::BaseRenderer* renderer); - - /** - * \brief Returns whether this is an vtk-based mapper - */ - virtual bool IsVtkBased() const { return false; } - - - - protected: - GLMapper2D(); - virtual ~GLMapper2D(); -}; + // typedef allows integration of mappers into the new mapper architecture + // @deprecated Use GLMapper instead + DEPRECATED(typedef GLMapper GLMapper2D); } // namespace mitk #endif /* MITKGLMAPPER2D_H_HEADER_INCLUDED_C197C872 */ diff --git a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp b/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp index 9c93cd002b..dbf0bd9e86 100644 --- a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp +++ b/Core/Code/Rendering/mitkGeometry2DDataMapper2D.cpp @@ -1,665 +1,665 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkGL.h" #include "mitkGeometry2DDataMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkSmartPointerProperty.h" #include "mitkPlaneOrientationProperty.h" #include "mitkGeometry2DDataToSurfaceFilter.h" #include "mitkSurfaceGLMapper2D.h" #include "mitkLine.h" #include "mitkNodePredicateDataType.h" #include "mitkResliceMethodProperty.h" mitk::Geometry2DDataMapper2D::Geometry2DDataMapper2D() : m_SurfaceMapper( NULL ), m_DataStorage(NULL), m_ParentNode(NULL), m_OtherGeometry2Ds(), m_RenderOrientationArrows( false ), m_ArrowOrientationPositive( true ) { } mitk::Geometry2DDataMapper2D::~Geometry2DDataMapper2D() { } const mitk::Geometry2DData* mitk::Geometry2DDataMapper2D::GetInput(void) { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } - -void mitk::Geometry2DDataMapper2D::GenerateData() +void mitk::Geometry2DDataMapper2D::GenerateDataForRenderer(mitk::BaseRenderer* /* renderer */) { // collect all Geometry2DDatas accessible from the DataStorage m_OtherGeometry2Ds.clear(); if (m_DataStorage.IsNull()) return; mitk::NodePredicateDataType::Pointer p = mitk::NodePredicateDataType::New("Geometry2DData"); mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetDerivations(m_ParentNode, p, false); for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { if(it->Value().IsNull()) continue; BaseData* data = it->Value()->GetData(); if (data == NULL) continue; Geometry2DData* geometry2dData = dynamic_cast(data); if(geometry2dData == NULL) continue; PlaneGeometry* planegeometry = dynamic_cast(geometry2dData->GetGeometry2D()); if (planegeometry != NULL) m_OtherGeometry2Ds.push_back(it->Value()); } } void mitk::Geometry2DDataMapper2D::Paint(BaseRenderer *renderer) { - if ( !this->IsVisible(renderer) ) - { - return; - } + bool visible = true; + + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if(!visible) return; Geometry2DData::Pointer input = const_cast< Geometry2DData * >(this->GetInput()); // intersecting with ourself? if ( input.IsNull() || (this->GetInput()->GetGeometry2D() == renderer->GetCurrentWorldGeometry2D()) ) { return; // do nothing! } const PlaneGeometry *inputPlaneGeometry = dynamic_cast< const PlaneGeometry * >( input->GetGeometry2D() ); const PlaneGeometry *worldPlaneGeometry = dynamic_cast< const PlaneGeometry* >( renderer->GetCurrentWorldGeometry2D() ); if ( worldPlaneGeometry && inputPlaneGeometry && inputPlaneGeometry->GetReferenceGeometry() ) { DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry(); assert( displayGeometry ); const Geometry3D *referenceGeometry = inputPlaneGeometry->GetReferenceGeometry(); // calculate intersection of the plane data with the border of the // world geometry rectangle Point2D lineFrom, lineTo; typedef Geometry3D::TransformType TransformType; const TransformType *transform = dynamic_cast< const TransformType * >( referenceGeometry->GetIndexToWorldTransform() ); TransformType::Pointer inverseTransform = TransformType::New(); transform->GetInverse( inverseTransform ); Line3D crossLine, otherCrossLine; // Calculate the intersection line of the input plane with the world plane if ( worldPlaneGeometry->IntersectionLine( inputPlaneGeometry, crossLine ) ) { BoundingBox::PointType boundingBoxMin, boundingBoxMax; boundingBoxMin = referenceGeometry->GetBoundingBox()->GetMinimum(); boundingBoxMax = referenceGeometry->GetBoundingBox()->GetMaximum(); if(referenceGeometry->GetImageGeometry()) { for(unsigned int i = 0; i < 3; ++i) { boundingBoxMin[i]-=0.5; boundingBoxMax[i]-=0.5; } } crossLine.Transform( *inverseTransform ); Point3D point1, point2; // Then, clip this line with the (transformed) bounding box of the // reference geometry. if ( crossLine.BoxLineIntersection( boundingBoxMin[0], boundingBoxMin[1], boundingBoxMin[2], boundingBoxMax[0], boundingBoxMax[1], boundingBoxMax[2], crossLine.GetPoint(), crossLine.GetDirection(), point1, point2 ) == 2 ) { // Transform the resulting line start and end points into display // coordinates. worldPlaneGeometry->Map( transform->TransformPoint( point1 ), lineFrom ); worldPlaneGeometry->Map( transform->TransformPoint( point2 ), lineTo ); Line< ScalarType, 2 > mainLine, otherLine; Line< ScalarType, 2 > primaryHelperLine, secondaryHelperLine; mainLine.SetPoints( lineFrom, lineTo ); primaryHelperLine.SetPoints( lineFrom, lineTo ); secondaryHelperLine.SetPoints( lineFrom, lineTo ); displayGeometry->WorldToDisplay( lineFrom, lineFrom ); displayGeometry->WorldToDisplay( lineTo, lineTo ); ScalarType lengthInDisplayUnits = (lineTo - lineFrom).GetNorm(); Vector2D mainLineDirectionOrthogonal; mainLineDirectionOrthogonal[0] = -mainLine.GetDirection()[1]; mainLineDirectionOrthogonal[1] = mainLine.GetDirection()[0]; // lineParams stores the individual segments of the line, which are // separated by a gap each (to mark the intersection with another // displayed line) std::vector< ScalarType > mainLineParams; std::vector< ScalarType > primaryHelperLineParams; std::vector< ScalarType > secondaryHelperLineParams; mainLineParams.reserve( m_OtherGeometry2Ds.size() + 2 ); mainLineParams.push_back( 0.0 ); mainLineParams.push_back( 1.0 ); primaryHelperLineParams.reserve( m_OtherGeometry2Ds.size() + 2 ); primaryHelperLineParams.push_back( 0.0 ); primaryHelperLineParams.push_back( 1.0 ); secondaryHelperLineParams.reserve( m_OtherGeometry2Ds.size() + 2 ); secondaryHelperLineParams.push_back( 0.0 ); secondaryHelperLineParams.push_back( 1.0 ); // Now iterate through all other lines displayed in this window and // calculate the positions of intersection with the line to be // rendered; these positions will be stored in lineParams to form a // gap afterwards. NodesVectorType::iterator otherPlanesIt = m_OtherGeometry2Ds.begin(); NodesVectorType::iterator otherPlanesEnd = m_OtherGeometry2Ds.end(); //int mainLineThickSlicesMode = 0; int mainLineThickSlicesNum = 1; DataNode* dataNodeOfInputPlaneGeometry = NULL; // Now we have to find the DataNode that contains the inputPlaneGeometry // in order to determine the state of the thick-slice rendering while ( otherPlanesIt != otherPlanesEnd ) { PlaneGeometry *otherPlane = static_cast< PlaneGeometry * >( static_cast< Geometry2DData * >( (*otherPlanesIt)->GetData() )->GetGeometry2D() ); // if we have found the correct node if ( (otherPlane == inputPlaneGeometry) && worldPlaneGeometry->IntersectionLine( otherPlane, otherCrossLine ) ) { dataNodeOfInputPlaneGeometry = (*otherPlanesIt); // if( dataNodeOfInputPlaneGeometry ) // { // mainLineThickSlicesMode = this->DetermineThickSliceMode(dataNodeOfInputPlaneGeometry, mainLineThickSlicesNum); // } break; } otherPlanesIt++; } // if we did not find a dataNode for the inputPlaneGeometry there is nothing we can do from here if ( dataNodeOfInputPlaneGeometry == NULL ) return; // Determine if we should draw the area covered by the thick slicing, default is false. // This will also show the area of slices that do not have thick slice mode enabled bool showAreaOfThickSlicing = false; dataNodeOfInputPlaneGeometry->GetBoolProperty( "reslice.thickslices.showarea", showAreaOfThickSlicing ); // get the normal of the inputPlaneGeometry Vector3D normal = inputPlaneGeometry->GetNormal(); // determine the pixelSpacing in that direction double thickSliceDistance = SlicedGeometry3D::CalculateSpacing( referenceGeometry->GetSpacing(), normal ); // As the inputPlaneGeometry cuts through the center of the slice in the middle // we have to add 0.5 pixel in order to compensate. thickSliceDistance *= mainLineThickSlicesNum+0.5; // not the nicest place to do it, but we have the width of the visible bloc in MM here // so we store it in this fancy property dataNodeOfInputPlaneGeometry->SetFloatProperty( "reslice.thickslices.sizeinmm", thickSliceDistance*2 ); if ( showAreaOfThickSlicing ) { // vectorToHelperLine defines how to reach the helperLine from the mainLine Vector2D vectorToHelperLine; vectorToHelperLine = mainLineDirectionOrthogonal; vectorToHelperLine.Normalize(); // got the right direction, so we multiply the width vectorToHelperLine *= thickSliceDistance; // and create the corresponding points primaryHelperLine.SetPoints( primaryHelperLine.GetPoint1() - vectorToHelperLine, primaryHelperLine.GetPoint2() - vectorToHelperLine ); secondaryHelperLine.SetPoints( secondaryHelperLine.GetPoint1() + vectorToHelperLine, secondaryHelperLine.GetPoint2() + vectorToHelperLine ); } //int otherLineThickSlicesMode = 0; int otherLineThickSlicesNum = 1; // by default, there is no gap for the helper lines ScalarType gapSize = 0.0; otherPlanesIt = m_OtherGeometry2Ds.begin(); while ( otherPlanesIt != otherPlanesEnd ) { PlaneGeometry *otherPlane = static_cast< PlaneGeometry * >( static_cast< Geometry2DData * >( (*otherPlanesIt)->GetData() )->GetGeometry2D() ); // Just as with the original line, calculate the intersection with // the world geometry... if ( (otherPlane != inputPlaneGeometry) && worldPlaneGeometry->IntersectionLine( otherPlane, otherCrossLine ) ) { //otherLineThickSlicesMode = this->DetermineThickSliceMode((*otherPlanesIt), otherLineThickSlicesNum); Vector3D normal = otherPlane->GetNormal(); double otherLineThickSliceDistance = SlicedGeometry3D::CalculateSpacing( referenceGeometry->GetSpacing(), normal ); otherLineThickSliceDistance *= (otherLineThickSlicesNum+0.5)*2; Point2D otherLineFrom, otherLineTo; // ... and clip the resulting line segment with the reference // geometry bounding box. otherCrossLine.Transform( *inverseTransform ); if ( otherCrossLine.BoxLineIntersection( boundingBoxMin[0], boundingBoxMin[1], boundingBoxMin[2], boundingBoxMax[0], boundingBoxMax[1], boundingBoxMax[2], otherCrossLine.GetPoint(), otherCrossLine.GetDirection(), point1, point2 ) == 2 ) { worldPlaneGeometry->Map( transform->TransformPoint( point1 ), otherLineFrom ); worldPlaneGeometry->Map( transform->TransformPoint( point2 ), otherLineTo ); otherLine.SetPoints( otherLineFrom, otherLineTo ); // then we have to determine the gap position of the main line // by finding the position at which the two lines cross this->DetermineParametricCrossPositions( mainLine, otherLine, mainLineParams ); // if the other line is also in thick slice mode, we have to determine the // gapsize considering the width of that other line and the spacing in its direction if ( showAreaOfThickSlicing ) { Vector2D otherLineDirection = otherLine.GetDirection(); otherLineDirection.Normalize(); mainLineDirectionOrthogonal.Normalize(); // determine the gapsize gapSize = fabs( otherLineThickSliceDistance / ( otherLineDirection*mainLineDirectionOrthogonal ) ); gapSize = gapSize / displayGeometry->GetScaleFactorMMPerDisplayUnit(); // determine the gap positions for the helper lines as well this->DetermineParametricCrossPositions( primaryHelperLine, otherLine, primaryHelperLineParams ); this->DetermineParametricCrossPositions( secondaryHelperLine, otherLine, secondaryHelperLineParams ); } } } ++otherPlanesIt; } // If we have to draw the helperlines, the mainline will be drawn as a dashed line // with a fixed gapsize of 10 pixels this->DrawLine(renderer, lengthInDisplayUnits, mainLine, mainLineParams, inputPlaneGeometry, showAreaOfThickSlicing, 10.0 ); // If drawn, the helperlines are drawn as a solid line. The gapsize depends on the // width of the crossed line. if ( showAreaOfThickSlicing ) { this->DrawLine(renderer, lengthInDisplayUnits, primaryHelperLine, primaryHelperLineParams, inputPlaneGeometry, false, gapSize ); this->DrawLine(renderer, lengthInDisplayUnits, secondaryHelperLine, secondaryHelperLineParams, inputPlaneGeometry, false, gapSize ); } } } } else { Geometry2DDataToSurfaceFilter::Pointer surfaceCreator; SmartPointerProperty::Pointer surfacecreatorprop; surfacecreatorprop = dynamic_cast< SmartPointerProperty * >( GetDataNode()->GetProperty( "surfacegeometry", renderer)); if( (surfacecreatorprop.IsNull()) || (surfacecreatorprop->GetSmartPointer().IsNull()) || ((surfaceCreator = dynamic_cast< Geometry2DDataToSurfaceFilter * >( surfacecreatorprop->GetSmartPointer().GetPointer())).IsNull()) ) { surfaceCreator = Geometry2DDataToSurfaceFilter::New(); surfacecreatorprop = SmartPointerProperty::New(surfaceCreator); surfaceCreator->PlaceByGeometryOn(); GetDataNode()->SetProperty( "surfacegeometry", surfacecreatorprop ); } surfaceCreator->SetInput( input ); // Clip the Geometry2D with the reference geometry bounds (if available) if ( input->GetGeometry2D()->HasReferenceGeometry() ) { surfaceCreator->SetBoundingBox( input->GetGeometry2D()->GetReferenceGeometry()->GetBoundingBox() ); } int res; bool usegeometryparametricbounds = true; if ( GetDataNode()->GetIntProperty("xresolution", res, renderer)) { surfaceCreator->SetXResolution(res); usegeometryparametricbounds=false; } if (GetDataNode()->GetIntProperty("yresolution", res, renderer)) { surfaceCreator->SetYResolution(res); usegeometryparametricbounds=false; } surfaceCreator->SetUseGeometryParametricBounds(usegeometryparametricbounds); // Calculate the surface of the Geometry2D surfaceCreator->Update(); if (m_SurfaceMapper.IsNull()) { m_SurfaceMapper=SurfaceGLMapper2D::New(); } m_SurfaceMapper->SetSurface(surfaceCreator->GetOutput()); m_SurfaceMapper->SetDataNode(GetDataNode()); m_SurfaceMapper->Paint(renderer); } } void mitk::Geometry2DDataMapper2D::DrawOrientationArrow( mitk::Point2D &outerPoint, mitk::Point2D &innerPoint, const mitk::PlaneGeometry *planeGeometry, const mitk::PlaneGeometry *rendererPlaneGeometry, const mitk::DisplayGeometry *displayGeometry, bool positiveOrientation ) { // Draw arrows to indicate plane orientation // Vector along line Vector2D v1 = innerPoint - outerPoint; v1.Normalize(); v1 *= 7.0; // Orthogonal vector Vector2D v2; v2[0] = v1[1]; v2[1] = -v1[0]; // Calculate triangle tip for one side and project it back into world // coordinates to determine whether it is above or below the plane Point2D worldPoint2D; Point3D worldPoint; displayGeometry->DisplayToWorld( outerPoint + v1 + v2, worldPoint2D ); rendererPlaneGeometry->Map( worldPoint2D, worldPoint ); // Initialize remaining triangle coordinates accordingly // (above/below state is XOR'ed with orientation flag) Point2D p1 = outerPoint + v1 * 2.0; Point2D p2 = outerPoint + v1 + ((positiveOrientation ^ planeGeometry->IsAbove( worldPoint )) ? v2 : -v2); // Draw the arrow (triangle) glBegin( GL_TRIANGLES ); glVertex2f( outerPoint[0], outerPoint[1] ); glVertex2f( p1[0], p1[1] ); glVertex2f( p2[0], p2[1] ); glEnd(); } -void mitk::Geometry2DDataMapper2D::ApplyProperties( BaseRenderer *renderer ) +void mitk::Geometry2DDataMapper2D::ApplyAllProperties( BaseRenderer *renderer ) { - Superclass::ApplyProperties(renderer); + Superclass::ApplyColorAndOpacityProperties(renderer); PlaneOrientationProperty* decorationProperty; this->GetDataNode()->GetProperty( decorationProperty, "decoration", renderer ); if ( decorationProperty != NULL ) { if ( decorationProperty->GetPlaneDecoration() == PlaneOrientationProperty::PLANE_DECORATION_POSITIVE_ORIENTATION ) { m_RenderOrientationArrows = true; m_ArrowOrientationPositive = true; } else if ( decorationProperty->GetPlaneDecoration() == PlaneOrientationProperty::PLANE_DECORATION_NEGATIVE_ORIENTATION ) { m_RenderOrientationArrows = true; m_ArrowOrientationPositive = false; } else { m_RenderOrientationArrows = false; } } } void mitk::Geometry2DDataMapper2D::SetDatastorageAndGeometryBaseNode( mitk::DataStorage::Pointer ds, mitk::DataNode::Pointer parent ) { if (ds.IsNotNull()) { m_DataStorage = ds; } if (parent.IsNotNull()) { m_ParentNode = parent; } } void mitk::Geometry2DDataMapper2D::DrawLine( BaseRenderer* renderer, ScalarType lengthInDisplayUnits, Line &line, std::vector &gapPositions, const PlaneGeometry* inputPlaneGeometry, bool drawDashed, ScalarType gapSizeInPixel ) { DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry(); const PlaneGeometry *worldPlaneGeometry = dynamic_cast< const PlaneGeometry* >( renderer->GetCurrentWorldGeometry2D() ); // Apply color and opacity read from the PropertyList. - this->ApplyProperties( renderer ); + this->ApplyAllProperties( renderer ); ScalarType gapSizeInParamUnits = 1.0 / lengthInDisplayUnits * gapSizeInPixel; std::sort( gapPositions.begin(), gapPositions.end() ); Point2D p1, p2; ScalarType p1Param, p2Param; p1Param = gapPositions[0]; p1 = line.GetPoint( p1Param ); displayGeometry->WorldToDisplay( p1, p1 ); //Workaround to show the crosshair always on top of a 2D render window //The image is usually located at depth = 0 or negative depth values, and thus, //the crosshair with depth = 1 is always on top. float depthPosition = 1.0f; if ( drawDashed ) { glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0xF0F0); } glEnable(GL_DEPTH_TEST); // Iterate over all line segments and display each, with a gap // in between. unsigned int i, preLastLineParam = gapPositions.size() - 1; for ( i = 1; i < preLastLineParam; ++i ) { p2Param = gapPositions[i] - gapSizeInParamUnits * 0.5; p2 = line.GetPoint( p2Param ); if ( p2Param > p1Param ) { // Convert intersection points (until now mm) to display // coordinates (units). displayGeometry->WorldToDisplay( p2, p2 ); // draw glBegin (GL_LINES); glVertex3f(p1[0],p1[1], depthPosition); glVertex3f(p2[0],p2[1], depthPosition); glEnd (); if ( (i == 1) && (m_RenderOrientationArrows) ) { // Draw orientation arrow for first line segment this->DrawOrientationArrow( p1, p2, inputPlaneGeometry, worldPlaneGeometry, displayGeometry, m_ArrowOrientationPositive ); } } p1Param = p2Param + gapSizeInParamUnits; p1 = line.GetPoint( p1Param ); displayGeometry->WorldToDisplay( p1, p1 ); } // Draw last line segment p2Param = gapPositions[i]; p2 = line.GetPoint( p2Param ); displayGeometry->WorldToDisplay( p2, p2 ); glBegin( GL_LINES ); glVertex3f( p1[0], p1[1], depthPosition); glVertex3f( p2[0], p2[1], depthPosition); glEnd(); if ( drawDashed ) { glDisable(GL_LINE_STIPPLE); } // Draw orientation arrows if ( m_RenderOrientationArrows ) { this->DrawOrientationArrow( p2, p1, inputPlaneGeometry, worldPlaneGeometry, displayGeometry, m_ArrowOrientationPositive ); if ( preLastLineParam < 2 ) { // If we only have one line segment, draw other arrow, too this->DrawOrientationArrow( p1, p2, inputPlaneGeometry, worldPlaneGeometry, displayGeometry, m_ArrowOrientationPositive ); } } } int mitk::Geometry2DDataMapper2D::DetermineThickSliceMode( DataNode * dn, int &thickSlicesNum ) { int thickSlicesMode = 0; // determine the state and the extend of the thick-slice mode mitk::ResliceMethodProperty *resliceMethodEnumProperty=0; if( dn->GetProperty( resliceMethodEnumProperty, "reslice.thickslices" ) && resliceMethodEnumProperty ) thickSlicesMode = resliceMethodEnumProperty->GetValueAsId(); IntProperty *intProperty=0; if( dn->GetProperty( intProperty, "reslice.thickslices.num" ) && intProperty ) { thickSlicesNum = intProperty->GetValue(); if(thickSlicesNum < 1) thickSlicesNum=0; if(thickSlicesNum > 10) thickSlicesNum=10; } if ( thickSlicesMode == 0 ) thickSlicesNum = 0; return thickSlicesMode; } void mitk::Geometry2DDataMapper2D::DetermineParametricCrossPositions( Line< mitk::ScalarType, 2 > &mainLine, Line< mitk::ScalarType, 2 > &otherLine, std::vector< mitk::ScalarType > &crossPositions ) { Vector2D direction, dOrth; // By means of the dot product, calculate the gap position as // parametric value in the range [0, 1] direction = otherLine.GetDirection(); dOrth[0] = -direction[1]; dOrth[1] = direction[0]; ScalarType gapPosition = ( otherLine.GetPoint1() - mainLine.GetPoint1() ) * dOrth; ScalarType norm = mainLine.GetDirection() * dOrth; if ( fabs( norm ) > eps ) { gapPosition /= norm; if ( (gapPosition > 0.0) && (gapPosition < 1.0) ) { crossPositions.push_back(gapPosition); } } } diff --git a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.h b/Core/Code/Rendering/mitkGeometry2DDataMapper2D.h index e39c0891b4..ff6e8a26ec 100644 --- a/Core/Code/Rendering/mitkGeometry2DDataMapper2D.h +++ b/Core/Code/Rendering/mitkGeometry2DDataMapper2D.h @@ -1,122 +1,121 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKGEOMETRY2DDATAMAPPER2D_H_HEADER_INCLUDED_C19C0BFB #define MITKGEOMETRY2DDATAMAPPER2D_H_HEADER_INCLUDED_C19C0BFB #include -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" #include "mitkSurfaceGLMapper2D.h" #include "mitkDataStorage.h" #include "mitkDataNode.h" #include "mitkWeakPointer.h" namespace mitk { class BaseRenderer; /** * \brief OpenGL-based mapper to display a Geometry2D in a 2D window * * Currently implemented for mapping on PlaneGeometry. * The result is normally a line. An important usage of this class is to show * the orientation of the slices displayed in other 2D windows. * * * Properties that can be set and influence the Geometry2DDataMapper2D are: * * - \b "PlaneOrientationProperty": (PlaneOrientationProperty) * \todo implement for AbstractTransformGeometry. * \ingroup Mapper */ -class MITK_CORE_EXPORT Geometry2DDataMapper2D : public GLMapper2D +class MITK_CORE_EXPORT Geometry2DDataMapper2D : public GLMapper { public: - mitkClassMacro(Geometry2DDataMapper2D, GLMapper2D); + mitkClassMacro(Geometry2DDataMapper2D, GLMapper); itkNewMacro(Self); /** * \brief Get the Geometry2DData to map */ const Geometry2DData *GetInput(); virtual void Paint( BaseRenderer *renderer ); virtual void SetDatastorageAndGeometryBaseNode(mitk::DataStorage::Pointer ds, mitk::DataNode::Pointer parent); /** Applies properties specific to this mapper */ - virtual void ApplyProperties( BaseRenderer *renderer ); + virtual void ApplyAllProperties( BaseRenderer *renderer ); protected: Geometry2DDataMapper2D(); virtual ~Geometry2DDataMapper2D(); - virtual void GenerateData(); - + virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); /** * \brief Returns the thick slice mode for the given datanode. * * This method returns the value of the 'reslice.thickslices' property for * the given datanode. * '0': thick slice mode disabled * '1': thick slice mode enabled * * The variable 'thickSlicesNum' contains the value of the 'reslice.thickslices.num' * property that defines how many slices are shown at once. */ int DetermineThickSliceMode( DataNode * dn, int &thickSlicesNum ); /** * \brief Determines the cross position of two lines and stores them as parametric coordinates * * This method determines the parametric position at which a line 'otherLine' crosses another line * 'mainLine'. The result is stored in 'crossPositions'. */ void DetermineParametricCrossPositions( Line &mainLine, Line &otherLine, std::vector &crossPositions ); void DrawLine( BaseRenderer * renderer, ScalarType lengthInDisplayUnits, Line< ScalarType, 2 > &line, std::vector< ScalarType > &gapPositions, const PlaneGeometry * inputPlaneGeometry, bool drawDashed, ScalarType gapSizeInPixel ); void DrawOrientationArrow( Point2D &outerPoint, Point2D &innerPoint, const PlaneGeometry *planeGeometry, const PlaneGeometry *rendererPlaneGeometry, const DisplayGeometry *displayGeometry, bool positiveOrientation = true ); SurfaceGLMapper2D::Pointer m_SurfaceMapper; mitk::WeakPointer m_DataStorage; ///< DataStorage that will be searched for sub nodes DataNode::Pointer m_ParentNode; ///< parent node that will be used to search for sub nodes typedef std::vector NodesVectorType; NodesVectorType m_OtherGeometry2Ds; bool m_RenderOrientationArrows; bool m_ArrowOrientationPositive; }; } // namespace mitk #endif /* MITKGEOMETRY2DDATAMAPPER2D_H_HEADER_INCLUDED_C19C0BFB */ diff --git a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp index afc74023d7..514fa1ac41 100644 --- a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp +++ b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.cpp @@ -1,588 +1,581 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkGeometry2DDataVtkMapper3D.h" #include "mitkImageVtkMapper2D.h" #include "mitkSmartPointerProperty.h" #include "mitkSurface.h" #include "mitkVtkRepresentationProperty.h" #include "mitkWeakPointerProperty.h" #include "mitkNodePredicateDataType.h" #include "mitkNodePredicateOr.h" #include "vtkNeverTranslucentTexture.h" +#include "vtkMitkLevelWindowFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace mitk { Geometry2DDataVtkMapper3D::Geometry2DDataVtkMapper3D() : m_NormalsActorAdded(false), m_DataStorage(NULL) { m_EdgeTuber = vtkTubeFilter::New(); m_EdgeMapper = vtkPolyDataMapper::New(); m_SurfaceCreator = Geometry2DDataToSurfaceFilter::New(); m_SurfaceCreatorBoundingBox = BoundingBox::New(); m_SurfaceCreatorPointsContainer = BoundingBox::PointsContainer::New(); m_Edges = vtkFeatureEdges::New(); m_Edges->BoundaryEdgesOn(); m_Edges->FeatureEdgesOff(); m_Edges->NonManifoldEdgesOff(); m_Edges->ManifoldEdgesOff(); m_EdgeTransformer = vtkTransformPolyDataFilter::New(); m_NormalsTransformer = vtkTransformPolyDataFilter::New(); m_EdgeActor = vtkActor::New(); m_BackgroundMapper = vtkPolyDataMapper::New(); m_BackgroundActor = vtkActor::New(); m_Prop3DAssembly = vtkAssembly::New(); m_ImageAssembly = vtkAssembly::New(); m_SurfaceCreatorBoundingBox->SetPoints( m_SurfaceCreatorPointsContainer ); m_Cleaner = vtkCleanPolyData::New(); m_Cleaner->PieceInvariantOn(); m_Cleaner->ConvertLinesToPointsOn(); m_Cleaner->ConvertPolysToLinesOn(); m_Cleaner->ConvertStripsToPolysOn(); m_Cleaner->PointMergingOn(); // Make sure that the FeatureEdge algorithm is initialized with a "valid" // (though empty) input vtkPolyData *emptyPolyData = vtkPolyData::New(); m_Cleaner->SetInput( emptyPolyData ); emptyPolyData->Delete(); m_Edges->SetInput(m_Cleaner->GetOutput()); m_EdgeTransformer->SetInput( m_Edges->GetOutput() ); m_EdgeTuber->SetInput( m_EdgeTransformer->GetOutput() ); m_EdgeTuber->SetVaryRadiusToVaryRadiusOff(); m_EdgeTuber->SetNumberOfSides( 12 ); m_EdgeTuber->CappingOn(); m_EdgeMapper->SetInput( m_EdgeTuber->GetOutput() ); m_EdgeMapper->ScalarVisibilityOff(); m_BackgroundMapper->SetInput(emptyPolyData); m_EdgeActor->SetMapper( m_EdgeMapper ); m_BackgroundActor->GetProperty()->SetAmbient( 0.5 ); m_BackgroundActor->GetProperty()->SetColor( 0.0, 0.0, 0.0 ); m_BackgroundActor->GetProperty()->SetOpacity( 0.0 ); m_BackgroundActor->SetMapper( m_BackgroundMapper ); vtkProperty * backfaceProperty = m_BackgroundActor->MakeProperty(); backfaceProperty->SetColor( 0.0, 0.0, 0.0 ); m_BackgroundActor->SetBackfaceProperty( backfaceProperty ); backfaceProperty->Delete(); m_FrontHedgeHog = vtkHedgeHog::New(); m_BackHedgeHog = vtkHedgeHog::New(); m_FrontNormalsMapper = vtkPolyDataMapper::New(); m_FrontNormalsMapper->SetInput( m_FrontHedgeHog->GetOutput() ); m_BackNormalsMapper = vtkPolyDataMapper::New(); m_Prop3DAssembly->AddPart( m_EdgeActor ); m_Prop3DAssembly->AddPart( m_ImageAssembly ); m_FrontNormalsActor = vtkActor::New(); m_FrontNormalsActor->SetMapper(m_FrontNormalsMapper); m_BackNormalsActor = vtkActor::New(); m_BackNormalsActor->SetMapper(m_BackNormalsMapper); m_ImageMapperDeletedCommand = MemberCommandType::New(); m_ImageMapperDeletedCommand->SetCallbackFunction( this, &Geometry2DDataVtkMapper3D::ImageMapperDeletedCallback ); } Geometry2DDataVtkMapper3D::~Geometry2DDataVtkMapper3D() { m_ImageAssembly->Delete(); m_Prop3DAssembly->Delete(); m_EdgeTuber->Delete(); m_EdgeMapper->Delete(); m_EdgeTransformer->Delete(); m_Cleaner->Delete(); m_Edges->Delete(); m_NormalsTransformer->Delete(); m_EdgeActor->Delete(); m_BackgroundMapper->Delete(); m_BackgroundActor->Delete(); m_FrontNormalsMapper->Delete(); m_FrontNormalsActor->Delete(); m_FrontHedgeHog->Delete(); m_BackNormalsMapper->Delete(); m_BackNormalsActor->Delete(); m_BackHedgeHog->Delete(); // Delete entries in m_ImageActors list one by one m_ImageActors.clear(); m_DataStorage = NULL; } vtkProp* Geometry2DDataVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) { if ( (this->GetDataNode() != NULL ) && (m_ImageAssembly != NULL) ) { // Do not transform the entire Prop3D assembly, but only the image part // here. The colored frame is transformed elsewhere (via m_EdgeTransformer), // since only vertices should be transformed there, not the poly data // itself, to avoid distortion for anisotropic datasets. m_ImageAssembly->SetUserTransform( this->GetDataNode()->GetVtkTransform() ); } return m_Prop3DAssembly; } void Geometry2DDataVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) { m_ImageAssembly->SetUserTransform( this->GetDataNode()->GetVtkTransform(this->GetTimestep()) ); } const Geometry2DData* Geometry2DDataVtkMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } void Geometry2DDataVtkMapper3D::SetDataStorageForTexture(mitk::DataStorage* storage) { if(storage != NULL && m_DataStorage != storage ) { m_DataStorage = storage; this->Modified(); } } void Geometry2DDataVtkMapper3D::ImageMapperDeletedCallback( itk::Object *caller, const itk::EventObject& /*event*/ ) { ImageVtkMapper2D *imageMapper = dynamic_cast< ImageVtkMapper2D * >( caller ); if ( (imageMapper != NULL) ) { if ( m_ImageActors.count( imageMapper ) > 0) { m_ImageActors[imageMapper].m_Sender = NULL; // sender is already destroying itself m_ImageActors.erase( imageMapper ); } } } void Geometry2DDataVtkMapper3D::GenerateDataForRenderer(BaseRenderer* renderer) { SetVtkMapperImmediateModeRendering(m_EdgeMapper); SetVtkMapperImmediateModeRendering(m_BackgroundMapper); // Remove all actors from the assembly, and re-initialize it with the // edge actor m_ImageAssembly->GetParts()->RemoveAllItems(); - if ( !this->IsVisible(renderer) ) + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible ) { // visibility has explicitly to be set in the single actors // due to problems when using cell picking: // even if the assembly is invisible, the renderer contains // references to the assemblies parts. During picking the // visibility of each part is checked, and not only for the // whole assembly. m_ImageAssembly->VisibilityOff(); m_EdgeActor->VisibilityOff(); return; } // visibility has explicitly to be set in the single actors // due to problems when using cell picking: // even if the assembly is invisible, the renderer contains // references to the assemblies parts. During picking the // visibility of each part is checked, and not only for the // whole assembly. m_ImageAssembly->VisibilityOn(); m_EdgeActor->VisibilityOn(); Geometry2DData::Pointer input = const_cast< Geometry2DData * >(this->GetInput()); if (input.IsNotNull() && (input->GetGeometry2D() != NULL)) { SmartPointerProperty::Pointer surfacecreatorprop; surfacecreatorprop = dynamic_cast< SmartPointerProperty * >(GetDataNode()->GetProperty("surfacegeometry", renderer)); if ( (surfacecreatorprop.IsNull()) || (surfacecreatorprop->GetSmartPointer().IsNull()) || ((m_SurfaceCreator = dynamic_cast (surfacecreatorprop->GetSmartPointer().GetPointer())).IsNull() ) ) { m_SurfaceCreator->PlaceByGeometryOn(); surfacecreatorprop = SmartPointerProperty::New( m_SurfaceCreator ); GetDataNode()->SetProperty("surfacegeometry", surfacecreatorprop); } m_SurfaceCreator->SetInput(input); int res; if (GetDataNode()->GetIntProperty("xresolution", res, renderer)) { m_SurfaceCreator->SetXResolution(res); } if (GetDataNode()->GetIntProperty("yresolution", res, renderer)) { m_SurfaceCreator->SetYResolution(res); } double tubeRadius = 1.0; // Radius of tubular edge surrounding plane // Clip the Geometry2D with the reference geometry bounds (if available) if ( input->GetGeometry2D()->HasReferenceGeometry() ) { Geometry3D *referenceGeometry = input->GetGeometry2D()->GetReferenceGeometry(); BoundingBox::PointType boundingBoxMin, boundingBoxMax; boundingBoxMin = referenceGeometry->GetBoundingBox()->GetMinimum(); boundingBoxMax = referenceGeometry->GetBoundingBox()->GetMaximum(); if ( referenceGeometry->GetImageGeometry() ) { for ( unsigned int i = 0; i < 3; ++i ) { boundingBoxMin[i] -= 0.5; boundingBoxMax[i] -= 0.5; } } m_SurfaceCreatorPointsContainer->CreateElementAt( 0 ) = boundingBoxMin; m_SurfaceCreatorPointsContainer->CreateElementAt( 1 ) = boundingBoxMax; m_SurfaceCreatorBoundingBox->ComputeBoundingBox(); m_SurfaceCreator->SetBoundingBox( m_SurfaceCreatorBoundingBox ); tubeRadius = referenceGeometry->GetDiagonalLength() / 450.0; } // If no reference geometry is available, clip with the current global // bounds else if (m_DataStorage.IsNotNull()) { m_SurfaceCreator->SetBoundingBox(m_DataStorage->ComputeVisibleBoundingBox(NULL, "includeInBoundingBox")); tubeRadius = sqrt( m_SurfaceCreator->GetBoundingBox()->GetDiagonalLength2() ) / 450.0; } // Calculate the surface of the Geometry2D m_SurfaceCreator->Update(); Surface *surface = m_SurfaceCreator->GetOutput(); // Check if there's something to display, otherwise return if ( (surface->GetVtkPolyData() == 0 ) || (surface->GetVtkPolyData()->GetNumberOfCells() == 0) ) { m_ImageAssembly->VisibilityOff(); return; } // add a graphical representation of the surface normals if requested DataNode* node = this->GetDataNode(); bool displayNormals = false; bool colorTwoSides = false; bool invertNormals = false; node->GetBoolProperty("draw normals 3D", displayNormals, renderer); node->GetBoolProperty("color two sides", colorTwoSides, renderer); node->GetBoolProperty("invert normals", invertNormals, renderer); //if we want to draw the display normals or render two sides we have to get the colors if( displayNormals || colorTwoSides ) { //get colors float frontColor[3] = { 0.0, 0.0, 1.0 }; node->GetColor( frontColor, renderer, "front color" ); float backColor[3] = { 1.0, 0.0, 0.0 }; node->GetColor( backColor, renderer, "back color" ); if ( displayNormals ) { m_NormalsTransformer->SetInput( surface->GetVtkPolyData() ); m_NormalsTransformer->SetTransform(node->GetVtkTransform(this->GetTimestep()) ); m_FrontHedgeHog->SetInput( m_NormalsTransformer->GetOutput() ); m_FrontHedgeHog->SetVectorModeToUseNormal(); m_FrontHedgeHog->SetScaleFactor( invertNormals ? 1.0 : -1.0 ); m_FrontNormalsActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); m_BackHedgeHog->SetInput( m_NormalsTransformer->GetOutput() ); m_BackHedgeHog->SetVectorModeToUseNormal(); m_BackHedgeHog->SetScaleFactor( invertNormals ? -1.0 : 1.0 ); m_BackNormalsActor->GetProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); //if there is no actor added yet, add one if ( !m_NormalsActorAdded ) { m_Prop3DAssembly->AddPart( m_FrontNormalsActor ); m_Prop3DAssembly->AddPart( m_BackNormalsActor ); m_NormalsActorAdded = true; } } //if we don't want to display normals AND there is an actor added remove the actor else if ( m_NormalsActorAdded ) { m_Prop3DAssembly->RemovePart( m_FrontNormalsActor ); m_Prop3DAssembly->RemovePart( m_BackNormalsActor ); m_NormalsActorAdded = false; } if ( colorTwoSides ) { if ( !invertNormals ) { m_BackgroundActor->GetProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); m_BackgroundActor->GetBackfaceProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); } else { m_BackgroundActor->GetProperty()->SetColor( frontColor[0], frontColor[1], frontColor[2] ); m_BackgroundActor->GetBackfaceProperty()->SetColor( backColor[0], backColor[1], backColor[2] ); } } } // Add black background for all images (which may be transparent) m_BackgroundMapper->SetInput( surface->GetVtkPolyData() ); m_ImageAssembly->AddPart( m_BackgroundActor ); LayerSortedActorList layerSortedActors; // Traverse the data tree to find nodes resliced by ImageMapperGL2D mitk::NodePredicateOr::Pointer p = mitk::NodePredicateOr::New(); //use a predicate to get all data nodes which are "images" or inherit from mitk::Image mitk::TNodePredicateDataType< mitk::Image >::Pointer predicateAllImages = mitk::TNodePredicateDataType< mitk::Image >::New(); mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetSubset(predicateAllImages); //process all found images for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) { DataNode *node = it->Value(); if (node != NULL) this->ProcessNode(node, renderer, surface, layerSortedActors); } // Add all image actors to the assembly, sorted according to // layer property LayerSortedActorList::iterator actorIt; for ( actorIt = layerSortedActors.begin(); actorIt != layerSortedActors.end(); ++actorIt ) { m_ImageAssembly->AddPart( actorIt->second ); } // Configurate the tube-shaped frame: size according to the surface // bounds, color as specified in the plane's properties vtkPolyData *surfacePolyData = surface->GetVtkPolyData(); m_Cleaner->SetInput(surfacePolyData); m_EdgeTransformer->SetTransform(this->GetDataNode()->GetVtkTransform(this->GetTimestep()) ); // Adjust the radius according to extent m_EdgeTuber->SetRadius( tubeRadius ); // Get the plane's color and set the tube properties accordingly ColorProperty::Pointer colorProperty; colorProperty = dynamic_cast(this->GetDataNode()->GetProperty( "color" )); if ( colorProperty.IsNotNull() ) { const Color& color = colorProperty->GetColor(); m_EdgeActor->GetProperty()->SetColor(color.GetRed(), color.GetGreen(), color.GetBlue()); } else { m_EdgeActor->GetProperty()->SetColor( 1.0, 1.0, 1.0 ); } m_ImageAssembly->SetUserTransform(this->GetDataNode()->GetVtkTransform(this->GetTimestep()) ); } VtkRepresentationProperty* representationProperty; this->GetDataNode()->GetProperty(representationProperty, "material.representation", renderer); if ( representationProperty != NULL ) m_BackgroundActor->GetProperty()->SetRepresentation( representationProperty->GetVtkRepresentation() ); } void Geometry2DDataVtkMapper3D::ProcessNode( DataNode * node, BaseRenderer* renderer, Surface * surface, LayerSortedActorList &layerSortedActors ) { if ( node != NULL ) { //we need to get the information from the 2D mapper to render the texture on the 3D plane ImageVtkMapper2D *imageMapper = dynamic_cast< ImageVtkMapper2D * >( node->GetMapper(1) ); //GetMapper(1) provides the 2D mapper for the data node //if there is a 2D mapper, which is not the standard image mapper... if(!imageMapper && node->GetMapper(1)) { //... check if it is the composite mapper std::string cname(node->GetMapper(1)->GetNameOfClass()); if(!cname.compare("CompositeMapper")) //string.compare returns 0 if the two strings are equal. { //get the standard image mapper. //This is a special case in MITK and does only work for the CompositeMapper. imageMapper = dynamic_cast( node->GetMapper(3) ); } } if ( (node->IsVisible(renderer)) && imageMapper ) { WeakPointerProperty::Pointer rendererProp = dynamic_cast< WeakPointerProperty * >(GetDataNode()->GetPropertyList()->GetProperty("renderer")); if ( rendererProp.IsNotNull() ) { BaseRenderer::Pointer planeRenderer = dynamic_cast< BaseRenderer * >(rendererProp->GetWeakPointer().GetPointer()); // Retrieve and update image to be mapped const ImageVtkMapper2D::LocalStorage* localStorage = imageMapper->GetLocalStorage(planeRenderer); if ( planeRenderer.IsNotNull() ) { // perform update of imagemapper if needed (maybe the respective 2D renderwindow is not rendered/update before) imageMapper->Update(planeRenderer); // If it has not been initialized already in a previous pass, // generate an actor and a texture object to // render the image associated with the ImageVtkMapper2D. vtkActor *imageActor; vtkDataSetMapper *dataSetMapper = NULL; vtkTexture *texture; if ( m_ImageActors.count( imageMapper ) == 0 ) { dataSetMapper = vtkDataSetMapper::New(); //Enable rendering without copying the image. dataSetMapper->ImmediateModeRenderingOn(); texture = vtkNeverTranslucentTexture::New(); texture->RepeatOff(); imageActor = vtkActor::New(); imageActor->SetMapper( dataSetMapper ); imageActor->SetTexture( texture ); imageActor->GetProperty()->SetOpacity(0.999); // HACK! otherwise VTK wouldn't recognize this as translucent surface (if LUT values map to alpha < 255 // improvement: apply "opacity" property onle HERE and also in 2D image mapper. DO NOT change LUT to achieve translucent images (see method ChangeOpacity in image mapper 2D) // Make imageActor the sole owner of the mapper and texture // objects dataSetMapper->UnRegister( NULL ); texture->UnRegister( NULL ); // Store the actor so that it may be accessed in following // passes. m_ImageActors[imageMapper].Initialize(imageActor, imageMapper, m_ImageMapperDeletedCommand); } else { // Else, retrieve the actor and associated objects from the // previous pass. imageActor = m_ImageActors[imageMapper].m_Actor; dataSetMapper = (vtkDataSetMapper *)imageActor->GetMapper(); texture = imageActor->GetTexture(); } // Set poly data new each time its object changes (e.g. when // switching between planar and curved geometries) if ( (dataSetMapper != NULL) && (dataSetMapper->GetInput() != surface->GetVtkPolyData()) ) { dataSetMapper->SetInput( surface->GetVtkPolyData() ); } //Check if the m_ReslicedImage is NULL. //This is the case when no image geometry is met by //the reslicer. In that case, the texture has to be //empty (black) and we don't have to do anything. //See fixed bug #13275 if(localStorage->m_ReslicedImage != NULL) { - bool binaryOutline = node->IsOn( "outline binary", renderer ); - if( binaryOutline ) - { - texture->SetInput( localStorage->m_ReslicedImage ); - } - else - { - texture->SetInput( localStorage->m_Texture->GetInput() ); - } - // VTK (mis-)interprets unsigned char (binary) images as color images; - // So, we must manually turn on their mapping through a (gray scale) lookup table; - texture->SetMapColorScalarsThroughLookupTable( localStorage->m_Texture->GetMapColorScalarsThroughLookupTable() ); + texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort()); + + // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter) + texture->MapColorScalarsThroughLookupTableOff(); //re-use properties from the 2D image mapper imageActor->SetProperty( localStorage->m_Actor->GetProperty() ); imageActor->GetProperty()->SetAmbient(0.5); // Set texture interpolation on/off bool textureInterpolation = node->IsOn( "texture interpolation", renderer ); texture->SetInterpolate( textureInterpolation ); - //get the lookuptable from the 2D image mapper - texture->SetLookupTable( localStorage->m_Texture->GetLookupTable() ); - // Store this actor to be added to the actor assembly, sort // by layer int layer = 1; node->GetIntProperty( "layer", layer ); layerSortedActors.insert(std::pair< int, vtkActor * >( layer, imageActor ) ); } } } } } } void Geometry2DDataVtkMapper3D::ActorInfo::Initialize(vtkActor* actor, itk::Object* sender, itk::Command* command) { m_Actor = actor; m_Sender = sender; // Get informed when ImageMapper object is deleted, so that // the data structures built here can be deleted as well m_ObserverID = sender->AddObserver( itk::DeleteEvent(), command ); } Geometry2DDataVtkMapper3D::ActorInfo::ActorInfo() : m_Actor(NULL), m_Sender(NULL), m_ObserverID(0) { } Geometry2DDataVtkMapper3D::ActorInfo::~ActorInfo() { if(m_Sender != NULL) { m_Sender->RemoveObserver(m_ObserverID); } if(m_Actor != NULL) { m_Actor->Delete(); } } } // namespace mitk diff --git a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h index f952d71697..9a6604ec63 100644 --- a/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h +++ b/Core/Code/Rendering/mitkGeometry2DDataVtkMapper3D.h @@ -1,210 +1,210 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKGEOMETRY2DDATAVTKMAPPER3D_H_HEADER_INCLUDED_C196C71F #define MITKGEOMETRY2DDATAVTKMAPPER3D_H_HEADER_INCLUDED_C196C71F #include -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include "mitkDataStorage.h" #include "mitkGeometry2DDataToSurfaceFilter.h" #include "mitkWeakPointer.h" #include #include class vtkActor; class vtkPolyDataMapper; class vtkAssembly; class vtkFeatureEdges; class vtkTubeFilter; class vtkTransformPolyDataFilter; class vtkHedgeHog; namespace mitk { class Geometry2DData; class BaseRenderer; class ImageVtkMapper2D; class DataStorage; /** * \brief Vtk-based mapper to display a Geometry2D in a 3D window * \ingroup Mapper * * Uses a Geometry2DDataToSurfaceFilter object to create a vtkPolyData representation of a given Geometry2D instance. * Geometry2D may either contain a common flat plane or a curved plane (ThinPlateSplineCurvedGeometry). * * The vtkPolyData object is then decorated by a colored tube on the edges and by image textures if possible * (currently this requires that there is a 2D render window rendering the same geometry as this mapper). * * Properties that influence rendering are: * * - \b "color": (ColorProperty) Color of the tubed frame. * - \b "xresolution": (FloatProperty) Resolution (=number of tiles) in x direction. Only relevant for ThinPlateSplineCurvedGeometry * - \b "yresolution": (FloatProperty) Resolution (=number of tiles) in y direction. Only relevant for ThinPlateSplineCurvedGeometry * - \b "draw normals 3D": (BoolProperty) If true, a vtkHedgeHog is used to display normals for the generated surface object. Useful to distinguish front and back of a plane. Hedgehogs are colored according to "front color" and "back color" * - \b "color two sides": (BoolProperty) If true, front and back side of the plane are colored differently ("front color" and "back color") * - \b "invert normals": (BoolProperty) Inverts front/back for display. * - \b "front color": (ColorProperty) Color for front side of the plane * - \b "back color": (ColorProperty) Color for back side of the plane * - \b "material.representation": (BoolProperty) Choose the representation to draw the mesh in (Surface, Wireframe, Point Cloud) * - \b "surfacegeometry": TODO: Add documentation * - \b "LookupTable": (LookupTableProperty) Set the lookuptable to render with. * * Note: The following properties are set for each image individually, and thus, also influence the rendering of this mapper: * * - \b "texture interpolation": (BoolProperty) Turn on/off the texture interpolation of each image * - \b "use color": (BoolProperty) Decide whether we want to use the color property or a lookuptable. * - \b "binary": (BoolProperty) Binary image handling: Color the value=1.0 with the color property and make the background (value=0.0) of the image translucent. * - \b "layer": (IntProperty) Controls what image is considered "on top" of another. In the case that two should inhabit the same space, higher layer occludes lower layer. * - \b "opacity": (FloatProperty) Set the opacity for each rendered image. * - \b "color": (FloatProperty) Set the color for each rendered image. * * The internal filter pipeline which combines a (sometimes deformed) 2D surface * with a nice frame and image textures is illustrated in the following sketch: * * \image html mitkGeometry2DDataVtkMapper3D.png "Internal filter pipeline" * */ -class MITK_CORE_EXPORT Geometry2DDataVtkMapper3D : public VtkMapper3D +class MITK_CORE_EXPORT Geometry2DDataVtkMapper3D : public VtkMapper { public: - mitkClassMacro(Geometry2DDataVtkMapper3D, VtkMapper3D); + mitkClassMacro(Geometry2DDataVtkMapper3D, VtkMapper); itkNewMacro(Geometry2DDataVtkMapper3D); /** * Overloaded since the displayed color-frame of the image mustn't be * transformed after generation of poly data, but before (vertex coordinates * only) */ virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer); /** * \brief Get the Geometry2DData to map */ virtual const Geometry2DData *GetInput(); /** * \brief All images found when traversing the (sub-) tree starting at * \a iterator which are resliced by an ImageVtkMapper2D will be mapped. * This method is used to set the data storage to traverse. This offers * the possibility to use this mapper for other data storages (not only * the default data storage). */ virtual void SetDataStorageForTexture(mitk::DataStorage* storage); protected: typedef std::multimap< int, vtkActor * > LayerSortedActorList; Geometry2DDataVtkMapper3D(); virtual ~Geometry2DDataVtkMapper3D(); virtual void GenerateDataForRenderer(BaseRenderer* renderer); void ProcessNode( DataNode * node, BaseRenderer* renderer, Surface * surface, LayerSortedActorList &layerSortedActors ); void ImageMapperDeletedCallback( itk::Object *caller, const itk::EventObject &event ); /** \brief general PropAssembly to hold the entire scene */ vtkAssembly *m_Prop3DAssembly; /** \brief PropAssembly to hold the planes */ vtkAssembly *m_ImageAssembly; Geometry2DDataToSurfaceFilter::Pointer m_SurfaceCreator; BoundingBox::Pointer m_SurfaceCreatorBoundingBox; BoundingBox::PointsContainer::Pointer m_SurfaceCreatorPointsContainer; /** \brief Edge extractor for tube-shaped frame */ vtkFeatureEdges *m_Edges; /** \brief Filter to apply object transform to the extracted edges */ vtkTransformPolyDataFilter *m_EdgeTransformer; /** \brief Source to create the tube-shaped frame */ vtkTubeFilter *m_EdgeTuber; /** \brief Mapper for the tube-shaped frame */ vtkPolyDataMapper *m_EdgeMapper; /** \brief Actor for the tube-shaped frame */ vtkActor *m_EdgeActor; /** \brief Mapper for black plane background */ vtkPolyDataMapper *m_BackgroundMapper; /** \brief Actor for black plane background */ vtkActor *m_BackgroundActor; /** \brief Transforms the suface before applying the glyph filter */ vtkTransformPolyDataFilter* m_NormalsTransformer; /** \brief Mapper for normals representation (thin lines) */ vtkPolyDataMapper* m_FrontNormalsMapper; vtkPolyDataMapper* m_BackNormalsMapper; /** \brief Generates lines for surface normals */ vtkHedgeHog* m_FrontHedgeHog; vtkHedgeHog* m_BackHedgeHog; /** \brief Actor to hold the normals arrows */ vtkActor* m_FrontNormalsActor; vtkActor* m_BackNormalsActor; /** Cleans the polyline in order to avoid phantom boundaries */ vtkCleanPolyData *m_Cleaner; /** Internal flag, if actors for normals are already added to m_Prop3DAssembly*/ bool m_NormalsActorAdded; /** \brief The DataStorage defines which part of the data tree is traversed for renderering. */ mitk::WeakPointer m_DataStorage; class MITK_CORE_EXPORT ActorInfo { public: vtkActor * m_Actor; // we do not need a smart-pointer, because we delete our // connection, when the referenced mapper is destroyed itk::Object* m_Sender; unsigned long m_ObserverID; void Initialize(vtkActor* actor, itk::Object* sender, itk::Command* command); ActorInfo(); ~ActorInfo(); }; /** \brief List holding the vtkActor to map the image into 3D for each * ImageMapper */ typedef std::map< ImageVtkMapper2D *, ActorInfo > ActorList; ActorList m_ImageActors; // responsiblity to remove the observer upon its destruction typedef itk::MemberCommand< Geometry2DDataVtkMapper3D > MemberCommandType; MemberCommandType::Pointer m_ImageMapperDeletedCommand; }; } // namespace mitk #endif /* MITKGEOMETRY2DDATAVTKMAPPER3D_H_HEADER_INCLUDED_C196C71F */ diff --git a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp index b8c83ceff4..d171a18839 100644 --- a/Core/Code/Rendering/mitkImageVtkMapper2D.cpp +++ b/Core/Code/Rendering/mitkImageVtkMapper2D.cpp @@ -1,1068 +1,1031 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //MITK #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include "mitkImageStatisticsHolder.h" #include "mitkPlaneClipping.h" //MITK Rendering #include "mitkImageVtkMapper2D.h" #include "vtkMitkThickSlicesFilter.h" #include "vtkMitkLevelWindowFilter.h" #include "vtkNeverTranslucentTexture.h" //VTK #include #include #include #include #include #include #include #include #include #include #include #include #include #include //ITK #include mitk::ImageVtkMapper2D::ImageVtkMapper2D() { } mitk::ImageVtkMapper2D::~ImageVtkMapper2D() { //The 3D RW Mapper (Geometry2DDataVtkMapper3D) is listening to this event, //in order to delete the images from the 3D RW. this->InvokeEvent( itk::DeleteEvent() ); } //set the two points defining the textured plane according to the dimension and spacing void mitk::ImageVtkMapper2D::GeneratePlane(mitk::BaseRenderer* renderer, vtkFloatingPointType planeBounds[6]) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); float depth = this->CalculateLayerDepth(renderer); //Set the origin to (xMin; yMin; depth) of the plane. This is necessary for obtaining the correct //plane size in crosshair rotation and swivel mode. localStorage->m_Plane->SetOrigin(planeBounds[0], planeBounds[2], depth); //These two points define the axes of the plane in combination with the origin. //Point 1 is the x-axis and point 2 the y-axis. //Each plane is transformed according to the view (axial, coronal and saggital) afterwards. localStorage->m_Plane->SetPoint1(planeBounds[1] , planeBounds[2], depth); //P1: (xMax, yMin, depth) localStorage->m_Plane->SetPoint2(planeBounds[0], planeBounds[3], depth); //P2: (xMin, yMax, depth) } float mitk::ImageVtkMapper2D::CalculateLayerDepth(mitk::BaseRenderer* renderer) { //get the clipping range to check how deep into z direction we can render images double maxRange = renderer->GetVtkRenderer()->GetActiveCamera()->GetClippingRange()[1]; //Due to a VTK bug, we cannot use the whole clipping range. /100 is empirically determined float depth = -maxRange*0.01; // divide by 100 int layer = 0; GetDataNode()->GetIntProperty( "layer", layer, renderer); //add the layer property for each image to render images with a higher layer on top of the others depth += layer*10; //*10: keep some room for each image (e.g. for QBalls in between) if(depth > 0.0f) { depth = 0.0f; MITK_WARN << "Layer value exceeds clipping range. Set to minimum instead."; } return depth; } const mitk::Image* mitk::ImageVtkMapper2D::GetInput( void ) { - return static_cast< const mitk::Image * >( this->GetData() ); + return static_cast< const mitk::Image * >( GetDataNode()->GetData() ); } vtkProp* mitk::ImageVtkMapper2D::GetVtkProp(mitk::BaseRenderer* renderer) { //return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Actors; } -void mitk::ImageVtkMapper2D::MitkRenderOverlay(BaseRenderer* renderer) -{ - if ( this->IsVisible(renderer)==false ) - return; - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); - } -} - -void mitk::ImageVtkMapper2D::MitkRenderOpaqueGeometry(BaseRenderer* renderer) -{ - if ( this->IsVisible( renderer )==false ) - return; - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); - } -} - -void mitk::ImageVtkMapper2D::MitkRenderTranslucentGeometry(BaseRenderer* renderer) -{ - if ( this->IsVisible(renderer)==false ) - return; - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); - } -} - -void mitk::ImageVtkMapper2D::MitkRenderVolumetricGeometry(BaseRenderer* renderer) -{ - if(IsVisible(renderer)==false) - return; - if ( GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); - } -} void mitk::ImageVtkMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); mitk::DataNode* datanode = this->GetDataNode(); if ( input == NULL || input->IsInitialized() == false ) { return; } //check if there is a valid worldGeometry const Geometry2D *worldGeometry = renderer->GetCurrentWorldGeometry2D(); if( ( worldGeometry == NULL ) || ( !worldGeometry->IsValid() ) || ( !worldGeometry->HasReferenceGeometry() )) { return; } input->Update(); // early out if there is no intersection of the current rendering geometry // and the geometry of the image that is to be rendered. if ( !RenderingGeometryIntersectsImage( worldGeometry, input->GetSlicedGeometry() ) ) { // set image to NULL, to clear the texture in 3D, because // the latest image is used there if the plane is out of the geometry // see bug-13275 localStorage->m_ReslicedImage = NULL; localStorage->m_Mapper->SetInput( localStorage->m_EmptyPolyData ); return; } //set main input for ExtractSliceFilter localStorage->m_Reslicer->SetInput(input); localStorage->m_Reslicer->SetWorldGeometry(worldGeometry); localStorage->m_Reslicer->SetTimeStep( this->GetTimestep() ); //set the transformation of the image to adapt reslice axis localStorage->m_Reslicer->SetResliceTransformByGeometry( input->GetTimeSlicedGeometry()->GetGeometry3D( this->GetTimestep() ) ); //is the geometry of the slice based on the input image or the worldgeometry? bool inPlaneResampleExtentByGeometry = false; datanode->GetBoolProperty("in plane resample extent by geometry", inPlaneResampleExtentByGeometry, renderer); localStorage->m_Reslicer->SetInPlaneResampleExtentByGeometry(inPlaneResampleExtentByGeometry); // Initialize the interpolation mode for resampling; switch to nearest // neighbor if the input image is too small. if ( (input->GetDimension() >= 3) && (input->GetDimension(2) > 1) ) { VtkResliceInterpolationProperty *resliceInterpolationProperty; datanode->GetProperty( resliceInterpolationProperty, "reslice interpolation" ); int interpolationMode = VTK_RESLICE_NEAREST; if ( resliceInterpolationProperty != NULL ) { interpolationMode = resliceInterpolationProperty->GetInterpolation(); } switch ( interpolationMode ) { case VTK_RESLICE_NEAREST: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); break; case VTK_RESLICE_LINEAR: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_LINEAR); break; case VTK_RESLICE_CUBIC: localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_CUBIC); break; } } else { localStorage->m_Reslicer->SetInterpolationMode(ExtractSliceFilter::RESLICE_NEAREST); } //set the vtk output property to true, makes sure that no unneeded mitk image convertion //is done. localStorage->m_Reslicer->SetVtkOutputRequest(true); //Thickslicing int thickSlicesMode = 0; int thickSlicesNum = 1; // Thick slices parameters if( input->GetPixelType().GetNumberOfComponents() == 1 ) // for now only single component are allowed { DataNode *dn=renderer->GetCurrentWorldGeometry2DNode(); if(dn) { ResliceMethodProperty *resliceMethodEnumProperty=0; if( dn->GetProperty( resliceMethodEnumProperty, "reslice.thickslices" ) && resliceMethodEnumProperty ) thickSlicesMode = resliceMethodEnumProperty->GetValueAsId(); IntProperty *intProperty=0; if( dn->GetProperty( intProperty, "reslice.thickslices.num" ) && intProperty ) { thickSlicesNum = intProperty->GetValue(); if(thickSlicesNum < 1) thickSlicesNum=1; if(thickSlicesNum > 10) thickSlicesNum=10; } } else { MITK_WARN << "no associated widget plane data tree node found"; } } const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( worldGeometry ); if(thickSlicesMode > 0) { double dataZSpacing = 1.0; Vector3D normInIndex, normal; if ( planeGeometry != NULL ){ normal = planeGeometry->GetNormal(); }else{ const mitk::AbstractTransformGeometry* abstractGeometry = dynamic_cast< const AbstractTransformGeometry * >(worldGeometry); if(abstractGeometry != NULL) normal = abstractGeometry->GetPlane()->GetNormal(); else return; //no fitting geometry set } normal.Normalize(); input->GetTimeSlicedGeometry()->GetGeometry3D( this->GetTimestep() )->WorldToIndex( normal, normInIndex ); dataZSpacing = 1.0 / normInIndex.GetNorm(); localStorage->m_Reslicer->SetOutputDimensionality( 3 ); localStorage->m_Reslicer->SetOutputSpacingZDirection(dataZSpacing); localStorage->m_Reslicer->SetOutputExtentZDirection( -thickSlicesNum, 0+thickSlicesNum ); // Do the reslicing. Modified() is called to make sure that the reslicer is // executed even though the input geometry information did not change; this // is necessary when the input /em data, but not the /em geometry changes. localStorage->m_TSFilter->SetThickSliceMode( thickSlicesMode-1 ); localStorage->m_TSFilter->SetInput( localStorage->m_Reslicer->GetVtkOutput() ); //vtkFilter=>mitkFilter=>vtkFilter update mechanism will fail without calling manually localStorage->m_Reslicer->Modified(); localStorage->m_Reslicer->Update(); localStorage->m_TSFilter->Modified(); localStorage->m_TSFilter->Update(); localStorage->m_ReslicedImage = localStorage->m_TSFilter->GetOutput(); } else { //this is needed when thick mode was enable bevore. These variable have to be reset to default values localStorage->m_Reslicer->SetOutputDimensionality( 2 ); localStorage->m_Reslicer->SetOutputSpacingZDirection(1.0); localStorage->m_Reslicer->SetOutputExtentZDirection( 0, 0 ); localStorage->m_Reslicer->Modified(); //start the pipeline with updating the largest possible, needed if the geometry of the input has changed localStorage->m_Reslicer->UpdateLargestPossibleRegion(); localStorage->m_ReslicedImage = localStorage->m_Reslicer->GetVtkOutput(); } // Bounds information for reslicing (only reuqired if reference geometry // is present) //this used for generating a vtkPLaneSource with the right size vtkFloatingPointType sliceBounds[6]; for ( int i = 0; i < 6; ++i ) { sliceBounds[i] = 0.0; } localStorage->m_Reslicer->GetClippedPlaneBounds(sliceBounds); //get the spacing of the slice localStorage->m_mmPerPixel = localStorage->m_Reslicer->GetOutputSpacing(); // calculate minimum bounding rect of IMAGE in texture vtkFloatingPointType textureClippingBounds[6]; for ( int i = 0; i < 6; ++i ) { textureClippingBounds[i] = 0.0; } // Calculate the actual bounds of the transformed plane clipped by the // dataset bounding box; this is required for drawing the texture at the // correct position during 3D mapping. mitk::PlaneClipping::CalculateClippedPlaneBounds( input->GetGeometry(), planeGeometry, textureClippingBounds ); textureClippingBounds[0] = static_cast< int >( textureClippingBounds[0] / localStorage->m_mmPerPixel[0] + 0.5 ); textureClippingBounds[1] = static_cast< int >( textureClippingBounds[1] / localStorage->m_mmPerPixel[0] + 0.5 ); textureClippingBounds[2] = static_cast< int >( textureClippingBounds[2] / localStorage->m_mmPerPixel[1] + 0.5 ); textureClippingBounds[3] = static_cast< int >( textureClippingBounds[3] / localStorage->m_mmPerPixel[1] + 0.5 ); //get the number of scalar components to distinguish between different image types int numberOfComponents = localStorage->m_ReslicedImage->GetNumberOfScalarComponents(); //get the binary property bool binary = false; bool binaryOutline = false; datanode->GetBoolProperty( "binary", binary, renderer ); if(binary) //binary image { datanode->GetBoolProperty( "outline binary", binaryOutline, renderer ); if(binaryOutline) //contour rendering { if ( input->GetPixelType().GetBpe() <= 8 ) { //generate contours/outlines localStorage->m_OutlinePolyData = CreateOutlinePolyData(renderer); float binaryOutlineWidth(1.0); if ( datanode->GetFloatProperty( "outline width", binaryOutlineWidth, renderer ) ) { if ( localStorage->m_Actors->GetNumberOfPaths() > 1 ) { float binaryOutlineShadowWidth(1.5); datanode->GetFloatProperty( "outline shadow width", binaryOutlineShadowWidth, renderer ); dynamic_cast(localStorage->m_Actors->GetParts()->GetItemAsObject(0)) ->GetProperty()->SetLineWidth( binaryOutlineWidth * binaryOutlineShadowWidth ); } localStorage->m_Actor->GetProperty()->SetLineWidth( binaryOutlineWidth ); } } else { binaryOutline = false; this->ApplyLookuptable(renderer, textureClippingBounds); MITK_WARN << "Type of all binary images should be (un)signed char. Outline does not work on other pixel types!"; } } else //standard binary image { if(numberOfComponents != 1) { MITK_ERROR << "Rendering Error: Binary Images with more then 1 component are not supported!"; } } } if (!(numberOfComponents == 1 || numberOfComponents == 3 || numberOfComponents == 4)) { MITK_WARN << "Unknown number of components!"; } this->ApplyLookuptable(renderer, textureClippingBounds); - // do not use a VTK lookup table (we do that ourselves in m_LevelWindowFilter) localStorage->m_Texture->MapColorScalarsThroughLookupTableOff(); this->ApplyColor( renderer ); this->ApplyOpacity( renderer ); this->TransformActor( renderer ); vtkActor* contourShadowActor = dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0)); if(binary && binaryOutline) //connect the mapper with the polyData which contains the lines { //We need the contour for the binary outline property as actor localStorage->m_Mapper->SetInput(localStorage->m_OutlinePolyData); localStorage->m_Actor->SetTexture(NULL); //no texture for contours bool binaryOutlineShadow( false ); datanode->GetBoolProperty( "outline binary shadow", binaryOutlineShadow, renderer ); if ( binaryOutlineShadow ) contourShadowActor->SetVisibility( true ); else contourShadowActor->SetVisibility( false ); } else { //Connect the mapper with the input texture. This is the standard case. //setup the textured plane this->GeneratePlane( renderer, sliceBounds ); //set the plane as input for the mapper localStorage->m_Mapper->SetInputConnection(localStorage->m_Plane->GetOutputPort()); //set the texture for the actor localStorage->m_Actor->SetTexture(localStorage->m_Texture); contourShadowActor->SetVisibility( false ); } // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } void mitk::ImageVtkMapper2D::ApplyColor( mitk::BaseRenderer* renderer ) { LocalStorage *localStorage = this->GetLocalStorage( renderer ); float rgb[3]= { 1.0f, 1.0f, 1.0f }; // check for color prop and use it for rendering if it exists // binary image hovering & binary image selection bool hover = false; bool selected = false; GetDataNode()->GetBoolProperty("binaryimage.ishovering", hover, renderer); GetDataNode()->GetBoolProperty("selected", selected, renderer); if(hover && !selected) { mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("binaryimage.hoveringcolor", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } else { - GetColor( rgb, renderer ); + GetDataNode()->GetColor( rgb, renderer, "color" ); } } if(selected) { mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("binaryimage.selectedcolor", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } else { - GetColor( rgb, renderer ); + GetDataNode()->GetColor(rgb, renderer, "color"); } } if(!hover && !selected) { - GetColor( rgb, renderer ); + GetDataNode()->GetColor( rgb, renderer, "color" ); } double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0))->GetProperty()->SetColor(rgbConv); localStorage->m_Actor->GetProperty()->SetColor(rgbConv); if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 ) { float rgb[3]= { 1.0f, 1.0f, 1.0f }; mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("outline binary shadow color", renderer)); if(colorprop.IsNotNull()) { memcpy(rgb, colorprop->GetColor().GetDataPointer(), 3*sizeof(float)); } double rgbConv[3] = {(double)rgb[0], (double)rgb[1], (double)rgb[2]}; //conversion to double for VTK dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetColor(rgbConv); } } void mitk::ImageVtkMapper2D::ApplyOpacity( mitk::BaseRenderer* renderer ) { LocalStorage* localStorage = this->GetLocalStorage( renderer ); float opacity = 1.0f; // check for opacity prop and use it for rendering if it exists - GetOpacity( opacity, renderer ); + GetDataNode()->GetOpacity( opacity, renderer, "opacity" ); //set the opacity according to the properties localStorage->m_Actor->GetProperty()->SetOpacity(opacity); if ( localStorage->m_Actors->GetParts()->GetNumberOfItems() > 1 ) { dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) )->GetProperty()->SetOpacity(opacity); } } void mitk::ImageVtkMapper2D::ApplyLookuptable( mitk::BaseRenderer* renderer, vtkFloatingPointType* bounds ) { //Have the following 4 different use cases how to generate the lookuptable: //1. We have a binary image -> The lut range is set to 0.0, 1.0 //2. The user sets a lut we can use //3. The user sets a transfer function we can use //4. Nothing defined: The default color lookuptable is used //@Warning: If the user sets a lut and a transfer function the lut will be used! LocalStorage* localStorage = m_LSH.GetLocalStorage(renderer); bool binary = false; this->GetDataNode()->GetBoolProperty( "binary", binary, renderer ); float blackOpacity = 0.0; if (!binary) { this->GetDataNode()->GetFloatProperty( "black opacity", blackOpacity, renderer); } vtkLookupTable *usedLookupTable = localStorage->m_DefaultLookupTable; vtkScalarsToColors *usedScalarsToColors = localStorage->m_DefaultLookupTable; // If lookup table or transferfunction use is requested... mitk::LookupTableProperty::Pointer lookupTableProp = dynamic_cast(this->GetDataNode()->GetProperty("LookupTable")); mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("Image Rendering.Transfer Function",renderer )); if(binary) // is it a binary image? { usedScalarsToColors = usedLookupTable = localStorage->m_BinaryLookupTable; } else if( lookupTableProp.IsNotNull() ) // is a lookuptable set? { if( transferFunctionProp.IsNotNull() ) { MITK_WARN << "A LookupTable and a transfer function TransferFunction property is set! Only the Image Rendering.Transfer Function will be used. If you want to use the color transfer function, remove or rename the LookupTable property."; } //If a lookup table is supplied by the user: //only update the lut, when the properties have changed... if( lookupTableProp->GetLookupTable()->GetMTime() <= this->GetDataNode()->GetPropertyList()->GetMTime() ) { lookupTableProp->GetLookupTable()->ChangeOpacityForAll( lookupTableProp->GetLookupTable()->GetVtkLookupTable()->GetAlpha()*localStorage->m_Actor->GetProperty()->GetOpacity() ); lookupTableProp->GetLookupTable()->ChangeOpacity(0, blackOpacity); } //If the user defines a lut, we dont want to use the color and take white instead. dynamic_cast (localStorage->m_Actors->GetParts()->GetItemAsObject(0))->GetProperty()->SetColor(1.0, 1.0, 1.0); localStorage->m_Actor->GetProperty()->SetColor(1.0, 1.0, 1.0); usedScalarsToColors = usedLookupTable = lookupTableProp->GetLookupTable()->GetVtkLookupTable(); } else if(transferFunctionProp.IsNotNull()) // is a color transfer function set? { usedScalarsToColors = transferFunctionProp->GetValue()->GetColorTransferFunction(); usedLookupTable = 0; } else { //default lookuptable LevelWindow levelWindow; - this->GetLevelWindow( levelWindow, renderer ); + GetDataNode()->GetLevelWindow( levelWindow, renderer, "levelwindow" ); usedLookupTable->SetRange( levelWindow.GetLowerWindowBound(), levelWindow.GetUpperWindowBound() ); - this->ApplyColor( renderer ); } - localStorage->m_Texture->SetInput( localStorage->m_ReslicedImage ); + this->ApplyColor( renderer ); // check for texture interpolation property bool textureInterpolation = false; GetDataNode()->GetBoolProperty( "texture interpolation", textureInterpolation, renderer ); //set the interpolation modus according to the property localStorage->m_Texture->SetInterpolate(textureInterpolation); mitk::LevelWindow opacLevelWindow; - if( this->GetLevelWindow( opacLevelWindow, renderer, "opaclevelwindow" ) ) + if( GetDataNode()->GetLevelWindow( opacLevelWindow, renderer, "opaclevelwindow" ) ) { //pass the opaque level window to the filter localStorage->m_LevelWindowFilter->SetMinOpacity(opacLevelWindow.GetLowerWindowBound()); localStorage->m_LevelWindowFilter->SetMaxOpacity(opacLevelWindow.GetUpperWindowBound()); } else { //no opaque level window localStorage->m_LevelWindowFilter->SetMinOpacity(0.0); localStorage->m_LevelWindowFilter->SetMaxOpacity(255.0); } localStorage->m_LevelWindowFilter->SetLookupTable(usedScalarsToColors); localStorage->m_LevelWindowFilter->SetInput(localStorage->m_ReslicedImage); localStorage->m_LevelWindowFilter->SetClippingBounds(bounds); //connect the texture with the output of the levelwindow filter localStorage->m_Texture->SetInputConnection(localStorage->m_LevelWindowFilter->GetOutputPort()); } void mitk::ImageVtkMapper2D::Update(mitk::BaseRenderer* renderer) { - if ( !this->IsVisible( renderer ) ) + + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible ) { return; } mitk::Image* data = const_cast( this->GetInput() ); if ( data == NULL ) { return; } // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep( renderer ); // Check if time step is valid const TimeSlicedGeometry *dataTimeGeometry = data->GetTimeSlicedGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->GetTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTime( this->GetTimestep() ) ) ) { return; } const DataNode *node = this->GetDataNode(); data->UpdateOutputInformation(); LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //check if something important has changed and we need to rerender if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified? || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { this->GenerateDataForRenderer( renderer ); } // since we have checked that nothing important has changed, we can set // m_LastUpdateTime to the current time localStorage->m_LastUpdateTime.Modified(); } void mitk::ImageVtkMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { mitk::Image::Pointer image = dynamic_cast(node->GetData()); // Properties common for both images and segmentations node->AddProperty( "depthOffset", mitk::FloatProperty::New( 0.0 ), renderer, overwrite ); node->AddProperty( "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "outline width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); node->AddProperty( "outline binary shadow", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "outline binary shadow color", ColorProperty::New(0.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "outline shadow width", mitk::FloatProperty::New( 1.5 ), renderer, overwrite ); if(image->IsRotated()) node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New(VTK_RESLICE_CUBIC) ); else node->AddProperty( "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ); node->AddProperty( "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ); // set to user configurable default value (see global options) node->AddProperty( "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ); node->AddProperty( "bounding box", mitk::BoolProperty::New( false ) ); std::string photometricInterpretation; // DICOM tag telling us how pixel values should be displayed if ( node->GetStringProperty( "dicom.pixel.PhotometricInterpretation", photometricInterpretation ) ) { // modality provided by DICOM or other reader if ( photometricInterpretation.find("MONOCHROME1") != std::string::npos ) // meaning: display MINIMUM pixels as WHITE { // generate LUT (white to black) mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); vtkLookupTable* bwLut = mitkLut->GetVtkLookupTable(); bwLut->SetTableRange (0, 1); bwLut->SetSaturationRange (0, 0); bwLut->SetHueRange (0, 0); bwLut->SetValueRange (1, 0); bwLut->SetAlphaRange (1, 1); bwLut->SetRampToLinear(); bwLut->Build(); mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty( "LookupTable", mitkLutProp ); } else if ( photometricInterpretation.find("MONOCHROME2") != std::string::npos ) // meaning: display MINIMUM pixels as BLACK { // apply default LUT (black to white) node->SetProperty( "color", mitk::ColorProperty::New( 1,1,1 ), renderer ); } // PALETTE interpretation should be handled ok by RGB loading } bool isBinaryImage(false); if ( ! node->GetBoolProperty("binary", isBinaryImage) ) { // ok, property is not set, use heuristic to determine if this // is a binary image mitk::Image::Pointer centralSliceImage; ScalarType minValue = 0.0; ScalarType maxValue = 0.0; ScalarType min2ndValue = 0.0; ScalarType max2ndValue = 0.0; mitk::ImageSliceSelector::Pointer sliceSelector = mitk::ImageSliceSelector::New(); sliceSelector->SetInput(image); sliceSelector->SetSliceNr(image->GetDimension(2)/2); sliceSelector->SetTimeNr(image->GetDimension(3)/2); sliceSelector->SetChannelNr(image->GetDimension(4)/2); sliceSelector->Update(); centralSliceImage = sliceSelector->GetOutput(); if ( centralSliceImage.IsNotNull() && centralSliceImage->IsInitialized() ) { minValue = centralSliceImage->GetStatistics()->GetScalarValueMin(); maxValue = centralSliceImage->GetStatistics()->GetScalarValueMax(); min2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMin(); max2ndValue = centralSliceImage->GetStatistics()->GetScalarValue2ndMax(); } if ((maxValue == min2ndValue && minValue == max2ndValue) || minValue == maxValue) { // centralSlice is strange, lets look at all data minValue = image->GetStatistics()->GetScalarValueMin(); maxValue = image->GetStatistics()->GetScalarValueMaxNoRecompute(); min2ndValue = image->GetStatistics()->GetScalarValue2ndMinNoRecompute(); max2ndValue = image->GetStatistics()->GetScalarValue2ndMaxNoRecompute(); } isBinaryImage = ( maxValue == min2ndValue && minValue == max2ndValue ); } // some more properties specific for a binary... if (isBinaryImage) { node->AddProperty( "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ); node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.selectedcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.selectedannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.hoveringcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binaryimage.hoveringannotationcolor", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( true ), renderer, overwrite ); node->AddProperty("layer", mitk::IntProperty::New(10), renderer, overwrite); } else //...or image type object { node->AddProperty( "opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite ); node->AddProperty( "black opacity", mitk::FloatProperty::New( 0.0 ), renderer, overwrite ); node->AddProperty( "color", ColorProperty::New(1.0,1.0,1.0), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty("layer", mitk::IntProperty::New(0), renderer, overwrite); } if(image.IsNotNull() && image->IsInitialized()) { if((overwrite) || (node->GetProperty("levelwindow", renderer)==NULL)) { /* initialize level/window from DICOM tags */ std::string sLevel; std::string sWindow; if ( image->GetPropertyList()->GetStringProperty( "dicom.voilut.WindowCenter", sLevel ) && image->GetPropertyList()->GetStringProperty( "dicom.voilut.WindowWidth", sWindow ) ) { float level = atof( sLevel.c_str() ); float window = atof( sWindow.c_str() ); mitk::LevelWindow contrast; std::string sSmallestPixelValueInSeries; std::string sLargestPixelValueInSeries; if ( image->GetPropertyList()->GetStringProperty( "dicom.series.SmallestPixelValueInSeries", sSmallestPixelValueInSeries ) && image->GetPropertyList()->GetStringProperty( "dicom.series.LargestPixelValueInSeries", sLargestPixelValueInSeries ) ) { float smallestPixelValueInSeries = atof( sSmallestPixelValueInSeries.c_str() ); float largestPixelValueInSeries = atof( sLargestPixelValueInSeries.c_str() ); contrast.SetRangeMinMax( smallestPixelValueInSeries-1, largestPixelValueInSeries+1 ); // why not a little buffer? // might remedy some l/w widget challenges } else { contrast.SetAuto( static_cast(node->GetData()), false, true ); // we need this as a fallback } contrast.SetLevelWindow( level, window, true ); node->SetProperty( "levelwindow", LevelWindowProperty::New( contrast ), renderer ); } } if(((overwrite) || (node->GetProperty("opaclevelwindow", renderer)==NULL)) && (image->GetPixelType().GetPixelTypeId() == itk::ImageIOBase::RGBA) && (image->GetPixelType().GetTypeId() == typeid( unsigned char)) ) { mitk::LevelWindow opaclevwin; opaclevwin.SetRangeMinMax(0,255); opaclevwin.SetWindowBounds(0,255); mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); node->SetProperty( "opaclevelwindow", prop, renderer ); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } mitk::ImageVtkMapper2D::LocalStorage* mitk::ImageVtkMapper2D::GetLocalStorage(mitk::BaseRenderer* renderer) { return m_LSH.GetLocalStorage(renderer); } vtkSmartPointer mitk::ImageVtkMapper2D::CreateOutlinePolyData(mitk::BaseRenderer* renderer ){ LocalStorage* localStorage = this->GetLocalStorage(renderer); //get the min and max index values of each direction int* extent = localStorage->m_ReslicedImage->GetExtent(); int xMin = extent[0]; int xMax = extent[1]; int yMin = extent[2]; int yMax = extent[3]; int* dims = localStorage->m_ReslicedImage->GetDimensions(); //dimensions of the image int line = dims[0]; //how many pixels per line? int x = xMin; //pixel index x int y = yMin; //pixel index y char* currentPixel; //get the depth for each contour float depth = CalculateLayerDepth(renderer); vtkSmartPointer points = vtkSmartPointer::New(); //the points to draw vtkSmartPointer lines = vtkSmartPointer::New(); //the lines to connect the points // We take the pointer to the first pixel of the image currentPixel = static_cast(localStorage->m_ReslicedImage->GetScalarPointer() ); while (y <= yMax) { //if the current pixel value is set to something if ((currentPixel) && (*currentPixel != 0)) { //check in which direction a line is necessary //a line is added if the neighbor of the current pixel has the value 0 //and if the pixel is located at the edge of the image //if vvvvv not the first line vvvvv if (y > yMin && *(currentPixel-line) == 0) { //x direction - bottom edge of the pixel //add the 2 points vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); //add the line between both points lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv not the last line vvvvv if (y < yMax && *(currentPixel+line) == 0) { //x direction - top edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv not the first pixel vvvvv if ( (x > xMin || y > yMin) && *(currentPixel-1) == 0) { //y direction - left edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv not the last pixel vvvvv if ( (y < yMax || (x < xMax) ) && *(currentPixel+1) == 0) { //y direction - right edge of the pixel vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } /* now consider pixels at the edge of the image */ //if vvvvv left edge of image vvvvv if (x == xMin) { //draw left edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv right edge of image vvvvv if (x == xMax) { //draw right edge of the pixel vtkIdType p1 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv bottom edge of image vvvvv if (y == yMin) { //draw bottom edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], y*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } //if vvvvv top edge of image vvvvv if (y == yMax) { //draw top edge of the pixel vtkIdType p1 = points->InsertNextPoint(x*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); vtkIdType p2 = points->InsertNextPoint((x+1)*localStorage->m_mmPerPixel[0], (y+1)*localStorage->m_mmPerPixel[1], depth); lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } }//end if currentpixel is set x++; if (x > xMax) { //reached end of line x = xMin; y++; } // Increase the pointer-position to the next pixel. // This is safe, as the while-loop and the x-reset logic above makes // sure we do not exceed the bounds of the image currentPixel++; }//end of while // Create a polydata to store everything in vtkSmartPointer polyData = vtkSmartPointer::New(); // Add the points to the dataset polyData->SetPoints(points); // Add the lines to the dataset polyData->SetLines(lines); return polyData; } void mitk::ImageVtkMapper2D::TransformActor(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //get the transformation matrix of the reslicer in order to render the slice as axial, coronal or saggital vtkSmartPointer trans = vtkSmartPointer::New(); vtkSmartPointer matrix = localStorage->m_Reslicer->GetResliceAxes(); trans->SetMatrix(matrix); //transform the plane/contour (the actual actor) to the corresponding view (axial, coronal or saggital) localStorage->m_Actor->SetUserTransform(trans); //transform the origin to center based coordinates, because MITK is center based. localStorage->m_Actor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0); if ( localStorage->m_Actors->GetNumberOfPaths() > 1 ) { vtkActor* secondaryActor = dynamic_cast( localStorage->m_Actors->GetParts()->GetItemAsObject(0) ); secondaryActor->SetUserTransform(trans); secondaryActor->SetPosition( -0.5*localStorage->m_mmPerPixel[0], -0.5*localStorage->m_mmPerPixel[1], 0.0); } } bool mitk::ImageVtkMapper2D::RenderingGeometryIntersectsImage( const Geometry2D* renderingGeometry, SlicedGeometry3D* imageGeometry ) { // if either one of the two geometries is NULL we return true // for safety reasons if ( renderingGeometry == NULL || imageGeometry == NULL ) return true; // get the distance for the first cornerpoint ScalarType initialDistance = renderingGeometry->SignedDistance( imageGeometry->GetCornerPoint( 0 ) ); for( int i=1; i<8; i++ ) { mitk::Point3D cornerPoint = imageGeometry->GetCornerPoint( i ); // get the distance to the other cornerpoints ScalarType distance = renderingGeometry->SignedDistance( cornerPoint ); // if it has not the same signing as the distance of the first point if ( initialDistance * distance < 0 ) { // we have an intersection and return true return true; } } // all distances have the same sign, no intersection and we return false return false; } mitk::ImageVtkMapper2D::LocalStorage::LocalStorage() { //Do as much actions as possible in here to avoid double executions. m_Plane = vtkSmartPointer::New(); m_Texture = vtkSmartPointer::New().GetPointer(); m_DefaultLookupTable = vtkSmartPointer::New(); m_BinaryLookupTable = vtkSmartPointer::New(); m_Mapper = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); m_Actors = vtkSmartPointer::New(); m_Reslicer = mitk::ExtractSliceFilter::New(); m_TSFilter = vtkSmartPointer::New(); m_OutlinePolyData = vtkSmartPointer::New(); m_ReslicedImage = vtkSmartPointer::New(); m_EmptyPolyData = vtkSmartPointer::New(); //the following actions are always the same and thus can be performed //in the constructor for each image (i.e. the image-corresponding local storage) m_TSFilter->ReleaseDataFlagOn(); //built a default lookuptable m_DefaultLookupTable->SetRampToLinear(); m_DefaultLookupTable->SetSaturationRange( 0.0, 0.0 ); m_DefaultLookupTable->SetHueRange( 0.0, 0.0 ); m_DefaultLookupTable->SetValueRange( 0.0, 1.0 ); m_DefaultLookupTable->Build(); m_BinaryLookupTable->SetRampToLinear(); m_BinaryLookupTable->SetSaturationRange( 0.0, 0.0 ); m_BinaryLookupTable->SetHueRange( 0.0, 0.0 ); m_BinaryLookupTable->SetValueRange( 0.0, 1.0 ); m_BinaryLookupTable->SetRange(0.0, 1.0); + m_BinaryLookupTable->Build(); // make first value transparent { double rgba[4]; m_BinaryLookupTable->GetTableValue(0, rgba); m_BinaryLookupTable->SetTableValue(0, rgba[0], rgba[1], rgba[2], 0); // background to 0 } - m_BinaryLookupTable->Build(); //do not repeat the texture (the image) m_Texture->RepeatOff(); //set the mapper for the actor m_Actor->SetMapper( m_Mapper ); vtkSmartPointer outlineShadowActor = vtkSmartPointer::New(); outlineShadowActor->SetMapper( m_Mapper ); m_Actors->AddPart( outlineShadowActor ); m_Actors->AddPart( m_Actor ); //level window filter m_LevelWindowFilter = new vtkMitkLevelWindowFilter(); } diff --git a/Core/Code/Rendering/mitkImageVtkMapper2D.h b/Core/Code/Rendering/mitkImageVtkMapper2D.h index 7e126814d3..59c068206e 100644 --- a/Core/Code/Rendering/mitkImageVtkMapper2D.h +++ b/Core/Code/Rendering/mitkImageVtkMapper2D.h @@ -1,297 +1,292 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E #define MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E //MITK #include //MITK Rendering #include "mitkBaseRenderer.h" -#include "mitkVtkMapper2D.h" +#include "mitkVtkMapper.h" #include "mitkExtractSliceFilter.h" //VTK #include #include class vtkActor; class vtkPolyDataMapper; class vtkPlaneSource; class vtkImageData; class vtkLookupTable; class vtkImageReslice; class vtkImageChangeInformation; class vtkPoints; class vtkMitkThickSlicesFilter; class vtkPolyData; class vtkMitkApplyLevelWindowToRGBFilter; class vtkMitkLevelWindowFilter; namespace mitk { /** \brief Mapper to resample and display 2D slices of a 3D image. * * The following image gives a brief overview of the mapping and the involved parts. * * \image html imageVtkMapper2Darchitecture.png * * First, the image is resliced by means of vtkImageReslice. The volume image * serves as input to the mapper in addition to spatial placement of the slice and a few other * properties such as thick slices. This code was already present in the old version * (mitkImageMapperGL2D). * * Next, the obtained slice (m_ReslicedImage) is put into a vtkMitkLevelWindowFilter * and the scalar levelwindow, opacity levelwindow and optional clipping to * local image bounds are applied * * Next, the output of the vtkMitkLevelWindowFilter is used to create a texture * (m_Texture) and a plane onto which the texture is rendered (m_Plane). For * mapping purposes, a vtkPolyDataMapper (m_Mapper) is utilized. Orthographic * projection is applied to create the effect of a 2D image. The mapper and the * texture are assigned to the actor (m_Actor) which is passed to the VTK rendering * pipeline via the method GetVtkProp(). * * In order to transform the textured plane to the correct position in space, the * same transformation as used for reslicing is applied to both the camera and the * vtkActor. All important steps are explained in more detail below. The resulting * 2D image (by reslicing the underlying 3D input image appropriately) can either * be directly rendered in a 2D view or just be calculated to be used later by another * rendering entity, e.g. in texture mapping in a 3D view. * * Properties that can be set for images and influence the imageMapper2D are: * * - \b "opacity": (FloatProperty) Opacity of the image * - \b "black opacity": (FloatProperty) The opacity of black (first index in lookup tables) * - \b "color": (ColorProperty) Color of the image * - \b "LookupTable": (mitkLookupTableProperty) If this property is set, * the default lookuptable will be ignored and the "LookupTable" value * will be used instead. * - \b "Image Rendering.Transfer Function": (mitkTransferFunctionProperty) If this * property is set, a color transferfunction will be used to color the image. * \warning This property will not have any effect if, the "LookupTable" property * is set. * - \b "binary": (BoolProperty) is the image a binary image or not * - \b "outline binary": (BoolProperty) show outline of the image or not * - \b "texture interpolation": (BoolProperty) texture interpolation of the image * - \b "reslice interpolation": (VtkResliceInterpolationProperty) reslice interpolation of the image * - \b "in plane resample extent by geometry": (BoolProperty) Do it or not * - \b "bounding box": (BoolProperty) Is the Bounding Box of the image shown or not * - \b "layer": (IntProperty) Layer of the image * - \b "volume annotation color": (ColorProperty) color of the volume annotation, TODO has to be reimplemented * - \b "volume annotation unit": (StringProperty) annotation unit as string (does not implicit convert the unit!) unit is ml or cm3, TODO has to be reimplemented * The default properties are: * - \b "opacity", mitk::FloatProperty::New(0.3f), renderer, overwrite ) * - \b "black opacity", mitk::FloatProperty::New(0.0f), renderer, overwrite ) * - \b "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ) * - \b "binary", mitk::BoolProperty::New( true ), renderer, overwrite ) * - \b "outline binary", mitk::BoolProperty::New( false ), renderer, overwrite ) * - \b "texture interpolation", mitk::BoolProperty::New( mitk::DataNodeFactory::m_TextureInterpolationActive ) ) * - \b "reslice interpolation", mitk::VtkResliceInterpolationProperty::New() ) * - \b "in plane resample extent by geometry", mitk::BoolProperty::New( false ) ) * - \b "bounding box", mitk::BoolProperty::New( false ) ) * - \b "layer", mitk::IntProperty::New(10), renderer, overwrite) * - \b "Image Rendering.Transfer Function": Default color transfer function for CTs * - \b "LookupTable": Undefined. Must be set by the user. * If the modality-property is set for an image, the mapper uses modality-specific default properties, * e.g. color maps, if they are defined. * \ingroup Mapper */ -class MITK_CORE_EXPORT ImageVtkMapper2D : public VtkMapper2D -{ + class MITK_CORE_EXPORT ImageVtkMapper2D : public VtkMapper + { -public: - /** Standard class typedefs. */ - mitkClassMacro( ImageVtkMapper2D,VtkMapper2D ); + public: + /** Standard class typedefs. */ + mitkClassMacro( ImageVtkMapper2D,VtkMapper ); /** Method for creation through the object factory. */ itkNewMacro(Self); /** \brief Get the Image to map */ const mitk::Image *GetInput(void); /** \brief Checks whether this mapper needs to update itself and generate * data. */ virtual void Update(mitk::BaseRenderer * renderer); - //### methods of MITK-VTK rendering pipeline - virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); - - virtual void MitkRenderOverlay(BaseRenderer* renderer); - virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer); - virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer); - virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer); - //### end of methods of MITK-VTK rendering pipeline + //### methods of MITK-VTK rendering pipeline + virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); + //### end of methods of MITK-VTK rendering pipeline /** \brief Internal class holding the mapper, actor, etc. for each of the 3 2D render windows */ /** * To render transveral, coronal, and sagittal, the mapper is called three times. * For performance reasons, the corresponding data for each view is saved in the * internal helper class LocalStorage. This allows rendering n views with just * 1 mitkMapper using n vtkMapper. * */ class MITK_CORE_EXPORT LocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Actor of a 2D render window. */ vtkSmartPointer m_Actor; vtkSmartPointer m_Actors; /** \brief Mapper of a 2D render window. */ vtkSmartPointer m_Mapper; /** \brief Current slice of a 2D render window.*/ vtkSmartPointer m_ReslicedImage; /** \brief Empty vtkPolyData that is set when rendering geometry does not * intersect the image geometry. * \warning This member variable is set to NULL, * if no image geometry is inside the plane geometry * of the respective render window. Any user of this * slice has to check whether it is set to NULL! */ vtkSmartPointer m_EmptyPolyData; /** \brief Plane on which the slice is rendered as texture. */ vtkSmartPointer m_Plane; /** \brief The texture which is used to render the current slice. */ vtkSmartPointer m_Texture; /** \brief The lookuptable for colors and level window */ vtkSmartPointer m_DefaultLookupTable; vtkSmartPointer m_BinaryLookupTable; /** \brief The actual reslicer (one per renderer) */ mitk::ExtractSliceFilter::Pointer m_Reslicer; /** \brief Filter for thick slices */ vtkSmartPointer m_TSFilter; /** \brief PolyData object containg all lines/points needed for outlining the contour. This container is used to save a computed contour for the next rendering execution. For instance, if you zoom or pann, there is no need to recompute the contour. */ vtkSmartPointer m_OutlinePolyData; /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief mmPerPixel relation between pixel and mm. (World spacing).*/ mitk::ScalarType* m_mmPerPixel; /** \brief This filter is used to apply the level window to Grayvalue and RBG(A) images. */ vtkMitkLevelWindowFilter* m_LevelWindowFilter; /** \brief Default constructor of the local storage. */ LocalStorage(); /** \brief Default deconstructor of the local storage. */ ~LocalStorage() { } }; /** \brief The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows. */ mitk::Mapper::LocalStorageHandler m_LSH; /** \brief Get the LocalStorage corresponding to the current renderer. */ LocalStorage* GetLocalStorage(mitk::BaseRenderer* renderer); /** \brief Set the default properties for general image rendering. */ static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); protected: /** \brief Transforms the actor to the actual position in 3D. * \param renderer The current renderer corresponding to the render window. */ void TransformActor(mitk::BaseRenderer* renderer); /** \brief Generates a plane according to the size of the resliced image in milimeters. * * \image html texturedPlane.png * * In VTK a vtkPlaneSource is defined through three points. The origin and two * points defining the axes of the plane (see VTK documentation). The origin is * set to (xMin; yMin; Z), where xMin and yMin are the minimal bounds of the * resliced image in space. Z is relevant for blending and the layer property. * The center of the plane (C) is also the center of the view plane (cf. the image above). * * \note For the standard MITK view with three 2D render windows showing three * different slices, three such planes are generated. All these planes are generated * in the XY-plane (even if they depict a YZ-slice of the volume). * */ void GeneratePlane(mitk::BaseRenderer* renderer, vtkFloatingPointType planeBounds[6]); /** \brief Generates a vtkPolyData object containing the outline of a given binary slice. \param renderer: Pointer to the renderer containing the needed information \note This code is based on code from the iil library. */ vtkSmartPointer CreateOutlinePolyData(mitk::BaseRenderer* renderer); /** Default constructor */ ImageVtkMapper2D(); /** Default deconstructor */ virtual ~ImageVtkMapper2D(); /** \brief Does the actual resampling, without rendering the image yet. * All the data is generated inside this method. The vtkProp (or Actor) * is filled with content (i.e. the resliced image). * * After generation, a 4x4 transformation matrix(t) of the current slice is obtained * from the vtkResliceImage object via GetReslicesAxis(). This matrix is * applied to each textured plane (actor->SetUserTransform(t)) to transform everything * to the actual 3D position (cf. the following image). * * \image html cameraPositioning3D.png * */ virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer); /** \brief This method uses the vtkCamera clipping range and the layer property * to calcualte the depth of the object (e.g. image or contour). The depth is used * to keep the correct order for the final VTK rendering.*/ float CalculateLayerDepth(mitk::BaseRenderer* renderer); /** \brief This method applies (or modifies) the lookuptable for all types of images. */ void ApplyLookuptable( mitk::BaseRenderer* renderer, vtkFloatingPointType* bounds ); /** \brief This method applies a color transfer function, if no LookuptableProperty is set. Internally, a vtkColorTransferFunction is used. This is usefull for coloring continous images (e.g. float) */ void ApplyColorTransferFunction(mitk::BaseRenderer* renderer); /** \brief Set the color of the image/polydata */ void ApplyColor( mitk::BaseRenderer* renderer ); /** \brief Set the opacity of the actor. */ void ApplyOpacity( mitk::BaseRenderer* renderer ); /** * \brief Calculates whether the given rendering geometry intersects the * given SlicedGeometry3D. * * This method checks if the given Geometry2D intersects the given * SlicedGeometry3D. It calculates the distance of the Geometry2D to all * 8 cornerpoints of the SlicedGeometry3D. If all distances have the same * sign (all positive or all negative) there is no intersection. * If the distances have different sign, there is an intersection. **/ bool RenderingGeometryIntersectsImage( const Geometry2D* renderingGeometry, SlicedGeometry3D* imageGeometry ); }; } // namespace mitk #endif /* MITKIMAGEVTKMAPPER2D_H_HEADER_INCLUDED_C10E906E */ diff --git a/Core/Code/Rendering/mitkMapper.cpp b/Core/Code/Rendering/mitkMapper.cpp index a03c64a96e..8a8e2ebe88 100644 --- a/Core/Code/Rendering/mitkMapper.cpp +++ b/Core/Code/Rendering/mitkMapper.cpp @@ -1,157 +1,150 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkMapper.h" #include "mitkDataNode.h" #include "mitkBaseRenderer.h" #include "mitkProperties.h" mitk::Mapper::Mapper() :m_TimeStep( 0 ) { - } mitk::Mapper::~Mapper() { } + mitk::BaseData* mitk::Mapper::GetData() const { - return m_DataNode->GetData(); +return m_DataNode->GetData(); } + mitk::DataNode* mitk::Mapper::GetDataNode() const { - itkDebugMacro("returning DataNode address " << this->m_DataNode ); return this->m_DataNode.GetPointer(); } bool mitk::Mapper::GetColor(float rgb[3], mitk::BaseRenderer* renderer, const char* name) const { const mitk::DataNode* node=GetDataNode(); if(node==NULL) return false; return node->GetColor(rgb, renderer, name); } bool mitk::Mapper::GetVisibility(bool &visible, mitk::BaseRenderer* renderer, const char* name) const { const mitk::DataNode* node=GetDataNode(); if(node==NULL) return false; return node->GetVisibility(visible, renderer, name); } bool mitk::Mapper::GetOpacity(float &opacity, mitk::BaseRenderer* renderer, const char* name) const { const mitk::DataNode* node=GetDataNode(); if(node==NULL) return false; return node->GetOpacity(opacity, renderer, name); } bool mitk::Mapper::GetLevelWindow(mitk::LevelWindow& levelWindow, mitk::BaseRenderer* renderer, const char* name) const { const mitk::DataNode* node=GetDataNode(); if(node==NULL) return false; return node->GetLevelWindow(levelWindow, renderer, name); } + bool mitk::Mapper::IsVisible(mitk::BaseRenderer* renderer, const char* name) const { - bool visible=true; - GetVisibility(visible, renderer, name); + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, name); return visible; } -void mitk::Mapper::GenerateData() -{ -} - -void mitk::Mapper::GenerateDataForRenderer(mitk::BaseRenderer* /*renderer*/) -{ -} void mitk::Mapper::CalculateTimeStep( mitk::BaseRenderer *renderer ) { if ( ( renderer != NULL ) && ( m_DataNode.GetPointer() != NULL ) ) { m_TimeStep = renderer->GetTimeStep(m_DataNode->GetData()); } else { m_TimeStep = 0; } } void mitk::Mapper::Update(mitk::BaseRenderer *renderer) { const DataNode* node = GetDataNode(); assert(node!=NULL); //safety cause there are datatreenodes that have no defined data (video-nodes and root) unsigned int dataMTime = 0; mitk::BaseData::Pointer data = static_cast(node->GetData()); if (data.IsNotNull()) { dataMTime = data->GetMTime(); } // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep( renderer ); // Check if time step is valid const TimeSlicedGeometry *dataTimeGeometry = data->GetTimeSlicedGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->GetTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTime( m_TimeStep ) ) ) { // TimeSlicedGeometry or time step is not valid for this data: // reset mapper so that nothing is displayed this->ResetMapper( renderer ); return; } if( (m_LastUpdateTime < GetMTime()) || (m_LastUpdateTime < node->GetDataReferenceChangedTime()) || (m_LastUpdateTime < dataMTime) || (renderer && (m_LastUpdateTime < renderer->GetTimeStepUpdateTime())) ) { - this->GenerateData(); m_LastUpdateTime.Modified(); } this->GenerateDataForRenderer(renderer); } void mitk::Mapper::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "visible", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "layer", mitk::IntProperty::New(0), renderer, overwrite); node->AddProperty( "name", mitk::StringProperty::New("No Name!"), renderer, overwrite ); } diff --git a/Core/Code/Rendering/mitkMapper.h b/Core/Code/Rendering/mitkMapper.h index cb7fc53ba3..74154a7fc6 100644 --- a/Core/Code/Rendering/mitkMapper.h +++ b/Core/Code/Rendering/mitkMapper.h @@ -1,282 +1,298 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MAPPER_H_HEADER_INCLUDED_C1E6EA08 #define MAPPER_H_HEADER_INCLUDED_C1E6EA08 #include #include "mitkBaseRenderer.h" +#include "mitkVtkPropRenderer.h" #include "mitkLevelWindow.h" +#include "mitkCommon.h" #include #include //Just included to get VTK version #include class vtkWindow; class vtkProp; namespace mitk { class BaseRenderer; class BaseData; class DataNode; /** \brief Interface for accessing (templated) LocalStorageHandler instances. */ class BaseLocalStorageHandler { public: virtual ~BaseLocalStorageHandler() {} virtual void ClearLocalStorage(mitk::BaseRenderer *renderer,bool unregisterFromBaseRenderer=true )=0; }; - //##Documentation - //## @brief Base class of all mappers, 2D as well as 3D - //## - //## Base class of all Mappers, 2D as well as 3D. - //## Subclasses of mitk::Mapper control the creation of rendering primitives - //## that interface to the graphics library (e.g., OpenGL, vtk). - //## @todo Should Mapper be a subclass of ImageSource? - //## @ingroup Mapper + /** \brief Base class of all mappers, Vtk as well as OpenGL mappers + * + * By the help of mappers, the input data is transformed to tangible primitives, + * such as surfaces, points, lines, etc. + * This is the base class of all mappers, Vtk as well as OpenGL mappers. + * Subclasses of mitk::Mapper control the creation of rendering primitives + * that interface to the graphics library (e.g., OpenGL, vtk). + * + * \todo Should Mapper be a subclass of ImageSource? + * \ingroup Mapper + */ class MITK_CORE_EXPORT Mapper : public itk::Object { public: mitkClassMacro(Mapper, itk::Object); - //##Documentation - //## @brief Set the DataNode containing the data to map + /** \brief Set the DataNode containing the data to map */ itkSetObjectMacro(DataNode, DataNode); - //##Documentation - //## @brief Get the data to map - //## - //## Returns the mitk::BaseData object associated with this mapper. - //## @returns the mitk::BaseData associated with this mapper. - BaseData* GetData() const; - //##Documentation - //## @brief Get the DataNode containing the data to map + /** \brief Get the DataNode containing the data to map */ virtual DataNode* GetDataNode() const; - //##Documentation - //## @brief Convenience access method for color properties (instances of - //## ColorProperty) - //## @return @a true property was found - virtual bool GetColor(float rgb[3], BaseRenderer* renderer, const char* name = "color") const; - - //##Documentation - //## @brief Convenience access method for visibility properties (instances - //## of BoolProperty) - //## @return @a true property was found - //## @sa IsVisible - virtual bool GetVisibility(bool &visible, BaseRenderer* renderer, const char* name = "visible") const; - - //##Documentation - //## @brief Convenience access method for opacity properties (instances of - //## FloatProperty) - //## @return @a true property was found - virtual bool GetOpacity(float &opacity, BaseRenderer* renderer, const char* name = "opacity") const; - - //##Documentation - //## @brief Convenience access method for color properties (instances of - //## LevelWindoProperty) - //## @return @a true property was found - virtual bool GetLevelWindow(LevelWindow &levelWindow, BaseRenderer* renderer, const char* name = "levelwindow") const; - - //##Documentation - //## @brief Convenience access method for visibility properties (instances - //## of BoolProperty). Return value is the visibility. Default is - //## visible==true, i.e., true is returned even if the property (@a - //## propertyKey) is not found. - //## - //## Thus, the return value has a different meaning than in the - //## GetVisibility method! - //## @sa GetVisibility - virtual bool IsVisible(BaseRenderer* renderer, const char* name = "visible") const; - virtual void Update(BaseRenderer* renderer); + /**\brief Get the data to map + * + * Returns the mitk::BaseData object associated with this mapper. + * \return the mitk::BaseData associated with this mapper. + * @deprecated Use GetDataNode()->GetData() instead to access the data + */ + DEPRECATED(BaseData* GetData() const); - virtual void MitkRenderOverlay(BaseRenderer* renderer) = 0; - virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer) = 0; - virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer) = 0; + /** \brief Convenience access method for color properties (instances of + * ColorProperty) + * \return \a true property was found + * @deprecated Use GetDataNode()->GetColor(...) instead to get the color + */ + DEPRECATED(virtual bool GetColor(float rgb[3], BaseRenderer* renderer, const char* name = "color") const); - virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer) = 0; + /** \brief Convenience access method for visibility properties (instances + * of BoolProperty) + * \return \a true property was found + * \sa IsVisible + * @deprecated Use GetDataNode()->GetVisibility(...) instead to get the visibility + */ + DEPRECATED(virtual bool GetVisibility(bool &visible, BaseRenderer* renderer, const char* name = "visible") const); - /** - * \brief Returns whether this is an vtk-based mapper + /** \brief Convenience access method for opacity properties (instances of + * FloatProperty) + * \return \a true property was found + * @deprecated Use GetDataNode()->GetOpacity(...) instead to get the opacity */ - virtual bool IsVtkBased() const = 0; + DEPRECATED(virtual bool GetOpacity(float &opacity, BaseRenderer* renderer, const char* name = "opacity") const); - /** \brief Returns true if this mapper owns the specified vtkProp for - * the given BaseRenderer. - * - * Note: returns false by default; should be implemented for VTK-based - * Mapper subclasses. */ - virtual bool HasVtkProp( const vtkProp* /*prop*/, BaseRenderer* /*renderer*/ ) - { - return false; - } + /** \brief Convenience access method for color properties (instances of + * LevelWindoProperty) + * \return \a true property was found + * @deprecated Use GetDataNode->GetLevelWindow(...) instead to get the levelwindow + */ + DEPRECATED(virtual bool GetLevelWindow(LevelWindow &levelWindow, BaseRenderer* renderer, const char* name = "levelwindow") const); + + + /** \brief Convenience access method for visibility properties (instances + * of BoolProperty). Return value is the visibility. Default is + * visible==true, i.e., true is returned even if the property (\a + * propertyKey) is not found. + * + * Thus, the return value has a different meaning than in the + * GetVisibility method! + * \sa GetVisibility + * @deprecated Use GetDataNode()->GetVisibility(...) instead + */ + DEPRECATED(virtual bool IsVisible(BaseRenderer* renderer, const char* name = "visible") const); + + + /** \brief Returns whether this is an vtk-based mapper + * @deprecated All mappers of superclass VTKMapper are vtk based, use a dynamic_cast instead + */ + virtual bool IsVtkBased() const = 0; + + + /** \brief Calls the time step of the input data for the specified renderer and checks + * whether the time step is valid and calls method GenerateDataForRenderer() + */ + virtual void Update(BaseRenderer* renderer); + + /** \brief Responsible for calling the appropriate render functions. + * To be implemented in sub-classes. + */ + virtual void MitkRender(mitk::BaseRenderer* renderer, mitk::VtkPropRenderer::RenderType type) = 0; /** - * \brief Release vtk-based graphics resources. Must be overwritten in - * subclasses if vtkProps are used. + * \brief Apply specific color and opacity properties read from the PropertyList. + * Reimplemented in GLmapper (does not use the actor) and the VtkMapper class. + * The function is called by the individual mapper (mostly in the ApplyProperties() or ApplyAllProperties() + * method). */ - virtual void ReleaseGraphicsResources(vtkWindow*) { }; + virtual void ApplyColorAndOpacityProperties(mitk::BaseRenderer* renderer, vtkActor* actor = NULL) = 0; + /** \brief Set default values of properties used by this mapper * to \a node * * \param node The node for which the properties are set * \param overwrite overwrite existing properties (default: \a false) * \param renderer defines which property list of node is used * (default: \a NULL, i.e. default property list) */ static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false); /** \brief Returns the current time step as calculated from the renderer */ - int GetTimestep() const {return m_TimeStep;}; - + int GetTimestep() const { return m_TimeStep; }; /** Returns true if this Mapper currently allows for Level-of-Detail rendering. * This reflects whether this Mapper currently invokes StartEvent, EndEvent, and * ProgressEvent on BaseRenderer. */ virtual bool IsLODEnabled( BaseRenderer * /*renderer*/ ) const { return false; } protected: - Mapper(); + /** \brief explicit constructor which disallows implicit conversions */ + explicit Mapper(); + /** \brief virtual destructor in order to derive from this class */ virtual ~Mapper(); - //##Documentation - //## @brief Generate the data needed for rendering (independent of a specific renderer) - virtual void GenerateData(); - //##Documentation - //## @brief Generate the data needed for rendering into @a renderer - virtual void GenerateDataForRenderer(BaseRenderer* renderer); - //## Updates the time step, which is sometimes needed in subclasses + /** \brief Generate the data needed for rendering (independent of a specific renderer) */ + // @deprecated Use GenerateDataForRenderer(BaseRenderer* renderer) instead. + DEPRECATED( virtual void GenerateData() { }); + + /** \brief Generate the data needed for rendering into \a renderer */ + virtual void GenerateDataForRenderer(BaseRenderer* /* renderer */) { }; + + /** \brief Updates the time step, which is sometimes needed in subclasses */ virtual void CalculateTimeStep( BaseRenderer* renderer ); - //## Reset the mapper (i.e., make sure that nothing is displayed) if no - //## valid data is present. - //## - //## To be implemented in sub-classes. + /** \brief Reset the mapper (i.e., make sure that nothing is displayed) if no + * valid data is present. In most cases the reimplemented function + * disables the according actors (toggling visibility off) + * + * To be implemented in sub-classes. + */ virtual void ResetMapper( BaseRenderer* /*renderer*/ ) { }; - + //\brief not thread-safe itk::WeakPointer m_DataNode; - //##Documentation - //## @brief timestamp of last update of stored data + /** \brief timestamp of last update of stored data */ itk::TimeStamp m_LastUpdateTime; private: - - //## The current time step of the dataset to be rendered, for use in subclasses - //## The momentary timestep can be accessed via the GetTimestep() method. + /** \brief The current time step of the dataset to be rendered, + * for use in subclasses. + * The current timestep can be accessed via the GetTimestep() method. + */ int m_TimeStep; + /** \brief copy constructor */ + Mapper( const Mapper &); + + /** \brief assignment operator */ + Mapper &operator=(const Mapper &); + public: /** \brief Base class for mapper specific rendering ressources. */ class BaseLocalStorage { }; /** \brief Templated class for management of LocalStorage implementations in Mappers. * * The LocalStorageHandler is responsible for providing a LocalStorage to a * concrete mitk::Mapper subclass. Each RenderWindow / mitk::BaseRenderer is * assigned its own LocalStorage instance so that all contained ressources * (actors, shaders, textures, ...) are provided individually per window. * */ template class LocalStorageHandler : public mitk::BaseLocalStorageHandler { protected: std::map m_BaseRenderer2LS; public: /** \brief deallocates a local storage for a specifc BaseRenderer (if the * BaseRenderer is itself deallocating it in its destructor, it has to set * unregisterFromBaseRenderer=false) */ virtual void ClearLocalStorage(mitk::BaseRenderer *renderer,bool unregisterFromBaseRenderer=true ) { //MITK_INFO << "deleting a localstorage on a mapper request"; if(unregisterFromBaseRenderer) renderer->UnregisterLocalStorageHandler( this ); L *l = m_BaseRenderer2LS[renderer]; m_BaseRenderer2LS.erase( renderer ); delete l; } /** \brief Retrieves a LocalStorage for a specific BaseRenderer. * - * Should be used by mappers in GenerateData() and ApplyProperties() + * Should be used by mappers in GenerateDataForRenderer() */ L *GetLocalStorage(mitk::BaseRenderer *forRenderer) { L *l = m_BaseRenderer2LS[ forRenderer ]; if(!l) { //MITK_INFO << "creating new localstorage"; l = new L; m_BaseRenderer2LS[ forRenderer ] = l; forRenderer->RegisterLocalStorageHandler( this ); } return l; } ~LocalStorageHandler() { typename std::map::iterator it; for ( it=m_BaseRenderer2LS.begin() ; it != m_BaseRenderer2LS.end(); it++ ) { (*it).first->UnregisterLocalStorageHandler(this); delete (*it).second; } m_BaseRenderer2LS.clear(); } }; - - - }; } // namespace mitk #endif /* MAPPER_H_HEADER_INCLUDED_C1E6EA08 */ diff --git a/Core/Code/Rendering/mitkMapper2D.cpp b/Core/Code/Rendering/mitkMapper2D.cpp deleted file mode 100644 index 0c8454bdc5..0000000000 --- a/Core/Code/Rendering/mitkMapper2D.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - - -#include "mitkMapper2D.h" - -mitk::Mapper2D::Mapper2D() -{ -} - -mitk::Mapper2D::~Mapper2D() -{ -} - -void mitk::Mapper2D::SetGeometry3D(const mitk::Geometry3D* aGeometry3D) -{ - m_Geometry3D = aGeometry3D; - Modified(); -} diff --git a/Core/Code/Rendering/mitkMapper2D.h b/Core/Code/Rendering/mitkMapper2D.h deleted file mode 100644 index f0ef27834d..0000000000 --- a/Core/Code/Rendering/mitkMapper2D.h +++ /dev/null @@ -1,63 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - - -#ifndef MAPPER2D_H_HEADER_INCLUDED_C1C5453B -#define MAPPER2D_H_HEADER_INCLUDED_C1C5453B - -#include "mitkMapper.h" -#include "mitkGeometry3D.h" - -namespace mitk { - -//##Documentation -//## @brief Base class of all Mappers for 2D display -//## -//## Base class of all Mappers for 2D display, i.e., a frontal view on a plane -//## display area, so nothing rotated in 3D space as, e.g., a plane in 3D space -//## (such things are done by subclasses of Mapper3D). -//## @note [not yet used:] SetGeometry3D() tells the Mapper2D which slices will -//## potentially be requested. -//## @ingroup Mapper -class MITK_CORE_EXPORT Mapper2D : public Mapper -{ - public: - mitkClassMacro(Mapper2D,Mapper); - - //##Documentation - //## @brief Set Geometry3D containing the all possible Geometry2D that may be requested for mapping - //## @sa m_Geometry3D - virtual void SetGeometry3D(const mitk::Geometry3D* aGeometry3D); - - protected: - Mapper2D(); - - virtual ~Mapper2D(); - - //##Documentation - //## @brief Set Geometry3D containing the all possible Geometry2D that may be requested for mapping - //## @note not yet implemented - //## The idea was that this allows storing/pre-fetching of data required for mapping. - //## Should be called by SliceNavigationController. - //## @todo check design and implement when implementing (sub-)classes of SliceNavigationController - Geometry3D::ConstPointer m_Geometry3D; -}; - -} // namespace mitk - - - -#endif /* MAPPER2D_H_HEADER_INCLUDED_C1C5453B */ diff --git a/Core/Code/Rendering/mitkMapper3D.cpp b/Core/Code/Rendering/mitkMapper3D.cpp deleted file mode 100644 index dc2eb48284..0000000000 --- a/Core/Code/Rendering/mitkMapper3D.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - - -#include "mitkMapper3D.h" - -mitk::Mapper3D::Mapper3D() -{ -} - -mitk::Mapper3D::~Mapper3D() -{ -} - diff --git a/Core/Code/Rendering/mitkMapper3D.h b/Core/Code/Rendering/mitkMapper3D.h deleted file mode 100644 index a4e4737467..0000000000 --- a/Core/Code/Rendering/mitkMapper3D.h +++ /dev/null @@ -1,44 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - - -#ifndef MAPPER3D_H_HEADER_INCLUDED_C1C517B9 -#define MAPPER3D_H_HEADER_INCLUDED_C1C517B9 - -#include "mitkMapper.h" - -namespace mitk { - -//##Documentation -//## @brief Base class of all mappers for 3D display -//## @ingroup Mapper -class MITK_CORE_EXPORT Mapper3D : public Mapper -{ - public: - mitkClassMacro(Mapper3D,Mapper); - - protected: - Mapper3D(); - - virtual ~Mapper3D(); - -}; - -} // namespace mitk - - - -#endif /* MAPPER3D_H_HEADER_INCLUDED_C1C517B9 */ diff --git a/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp b/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp index 4979ad3366..e81aa8ddf1 100644 --- a/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp +++ b/Core/Code/Rendering/mitkPointSetGLMapper2D.cpp @@ -1,534 +1,536 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPointSetGLMapper2D.h" #include "mitkPointSet.h" #include "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "vtkLinearTransform.h" #include "mitkStringProperty.h" #include "mitkPointSet.h" #include "mitkVtkPropRenderer.h" #include "mitkGL.h" //const float selectedColor[]={1.0,0.0,0.6}; //for selected! mitk::PointSetGLMapper2D::PointSetGLMapper2D() : m_Polygon(false), m_ShowPoints(true), m_ShowDistances(false), m_DistancesDecimalDigits(1), m_ShowAngles(false), m_ShowDistantLines(true), m_LineWidth(1), m_ShowDistantPoints(true) { } mitk::PointSetGLMapper2D::~PointSetGLMapper2D() { } const mitk::PointSet *mitk::PointSetGLMapper2D::GetInput(void) { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } -void mitk::PointSetGLMapper2D::ApplyProperties(mitk::BaseRenderer* renderer) +void mitk::PointSetGLMapper2D::ApplyAllProperties(mitk::BaseRenderer* renderer) { - GLMapper2D::ApplyProperties( renderer ); + GLMapper::ApplyColorAndOpacityProperties( renderer ); const mitk::DataNode* node=GetDataNode(); if( node == NULL ) return; node->GetBoolProperty("show contour", m_Polygon); node->GetBoolProperty("close contour", m_PolygonClosed); node->GetBoolProperty("show points", m_ShowPoints); node->GetBoolProperty("show distances", m_ShowDistances); node->GetIntProperty("distance decimal digits", m_DistancesDecimalDigits); node->GetBoolProperty("show angles", m_ShowAngles); node->GetBoolProperty("show distant lines", m_ShowDistantLines); node->GetIntProperty("line width", m_LineWidth); node->GetIntProperty("point line width", m_PointLineWidth); node->GetIntProperty("point 2D size", m_Point2DSize); node->GetBoolProperty("show distant points", m_ShowDistantPoints); } static bool makePerpendicularVector2D(const mitk::Vector2D& in, mitk::Vector2D& out) { if((fabs(in[0])>0) && ( (fabs(in[0])>fabs(in[1])) || (in[1] == 0) ) ) { out[0]=-in[1]/in[0]; out[1]=1; out.Normalize(); return true; } else if(fabs(in[1])>0) { out[0]=1; out[1]=-in[0]/in[1]; out.Normalize(); return true; } else return false; } void mitk::PointSetGLMapper2D::Paint( mitk::BaseRenderer *renderer ) { const mitk::DataNode* node=GetDataNode(); if( node == NULL ) return; const int text2dDistance = 10; - if(IsVisible(renderer)==false) return; + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + if ( !visible) return; // @FIXME: Logik fuer update bool updateNeccesary=true; if (updateNeccesary) { // ok, das ist aus GenerateData kopiert mitk::PointSet::Pointer input = const_cast(this->GetInput()); // Get the TimeSlicedGeometry of the input object const TimeSlicedGeometry* inputTimeGeometry = input->GetTimeSlicedGeometry(); if (( inputTimeGeometry == NULL ) || ( inputTimeGeometry->GetTimeSteps() == 0 ) ) { return; } // // get the world time // const Geometry2D* worldGeometry = renderer->GetCurrentWorldGeometry2D(); assert( worldGeometry != NULL ); ScalarType time = worldGeometry->GetTimeBounds()[ 0 ]; // // convert the world time in time steps of the input object // int timeStep=0; if ( time > ScalarTypeNumericTraits::NonpositiveMin() ) timeStep = inputTimeGeometry->MSToTimeStep( time ); if ( inputTimeGeometry->IsValidTime( timeStep ) == false ) { return; } mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet( timeStep ); if ( itkPointSet.GetPointer() == NULL) { return; } mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert(displayGeometry.IsNotNull()); //apply color and opacity read from the PropertyList - ApplyProperties(renderer); + this->ApplyAllProperties(renderer); vtkLinearTransform* transform = GetDataNode()->GetVtkTransform(); //List of the Points PointSet::DataType::PointsContainerConstIterator it, end; it = itkPointSet->GetPoints()->Begin(); end = itkPointSet->GetPoints()->End(); //iterator on the additional data of each point PointSet::DataType::PointDataContainerIterator selIt, selEnd; bool pointDataBroken = (itkPointSet->GetPointData()->Size() != itkPointSet->GetPoints()->Size()); selIt = itkPointSet->GetPointData()->Begin(); selEnd = itkPointSet->GetPointData()->End(); int counter = 0; //for writing text int j = 0; //for switching back to old color after using selected color float recallColor[4]; glGetFloatv(GL_CURRENT_COLOR,recallColor); //get the properties for coloring the points float unselectedColor[4] = {1.0, 1.0, 0.0, 1.0};//yellow //check if there is an unselected property if (dynamic_cast(node->GetPropertyList(renderer)->GetProperty("unselectedcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("unselectedcolor"))->GetValue(); unselectedColor[0] = tmpColor[0]; unselectedColor[1] = tmpColor[1]; unselectedColor[2] = tmpColor[2]; unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value } else if (dynamic_cast(node->GetPropertyList(NULL)->GetProperty("unselectedcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("unselectedcolor"))->GetValue(); unselectedColor[0] = tmpColor[0]; unselectedColor[1] = tmpColor[1]; unselectedColor[2] = tmpColor[2]; unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value } else { //get the color from the dataNode node->GetColor(unselectedColor, NULL); } //get selected property float selectedColor[4] = {1.0, 0.0, 0.6, 1.0}; if (dynamic_cast(node->GetPropertyList(renderer)->GetProperty("selectedcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor"))->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; } else if (dynamic_cast(node->GetPropertyList(NULL)->GetProperty("selectedcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor"))->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; } //check if there is an pointLineWidth property if (dynamic_cast(node->GetPropertyList(renderer)->GetProperty("point line width")) != NULL) { m_PointLineWidth = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("point line width"))->GetValue(); } else if (dynamic_cast(node->GetPropertyList(NULL)->GetProperty("point line width")) != NULL) { m_PointLineWidth = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("point line width"))->GetValue(); } //check if there is an point 2D size property if (dynamic_cast(node->GetPropertyList(renderer)->GetProperty("point 2D size")) != NULL) { m_Point2DSize = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("point 2D size"))->GetValue(); } else if (dynamic_cast(node->GetPropertyList(NULL)->GetProperty("point 2D size")) != NULL) { m_Point2DSize = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("point 2D size"))->GetValue(); } Point3D p; // currently visited point Point3D lastP; // last visited point Vector3D vec; // p - lastP Vector3D lastVec; // lastP - point before lastP vec.Fill(0); mitk::Point3D projected_p; // p projected on viewplane Point2D pt2d; // projected_p in display coordinates Point2D lastPt2d; // last projected_p in display coordinates Point2D preLastPt2d;// projected_p in display coordinates before lastPt2d Point2D lastPt2DInPointSet; // The last point in the pointset in display coordinates mitk::PointSet::DataType::PointType plob; plob.Fill(0); itkPointSet->GetPoint( itkPointSet->GetNumberOfPoints()-1, &plob); //map lastPt2DInPointSet to display coordinates float vtkp[3]; itk2vtk(plob, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, lastPt2DInPointSet); displayGeometry->WorldToDisplay(lastPt2DInPointSet, lastPt2DInPointSet); while(it!=end) // iterate over all points { lastP = p; // valid only for counter > 0 lastVec = vec; // valid only for counter > 1 preLastPt2d = lastPt2d; // valid only for counter > 1 lastPt2d = pt2d; // valid only for counter > 0 itk2vtk(it->Value(), vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); vec = p-lastP; // valid only for counter > 0 displayGeometry->Project(p, projected_p); Vector3D diff=p-projected_p; ScalarType scalardiff = diff.GetSquaredNorm(); //MouseOrientation bool isInputDevice=false; double scalarDiffTolerance = 0.00001; //cause roundoff error bool isRendererSlice = scalardiff < scalarDiffTolerance; if(this->GetDataNode()->GetBoolProperty("inputdevice",isInputDevice) && isInputDevice && !isRendererSlice ) { displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); //Point size depending of distance to slice /*float p_size = (1/scalardiff)*10*m_Point2DSize; if(p_size < m_Point2DSize * 0.6 ) p_size = m_Point2DSize * 0.6 ; else if ( p_size > m_Point2DSize ) p_size = m_Point2DSize;*/ float p_size = (1/scalardiff)*100.0; if(p_size < 6.0 ) p_size = 6.0 ; else if ( p_size > 10.0 ) p_size = 10.0; //draw Point float opacity = (p_size<8)?0.3:1.0;//don't get the opacity from the node? Feature not a bug! Otehrwise the 2D cross is hardly seen. glColor4f(unselectedColor[0],unselectedColor[1],unselectedColor[2],opacity); glPointSize(p_size); //glShadeModel(GL_FLAT); glBegin (GL_POINTS); glVertex2fv(&pt2d[0]); glEnd (); } //for point set if(!isInputDevice && ( (m_ShowDistantPoints && scalardiff < 4.0) || (!m_ShowDistantPoints && scalardiff < scalarDiffTolerance) || (m_Polygon) ) ) { Point2D tmp; displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); Vector2D horz,vert; horz[0]=(float)m_Point2DSize-scalardiff*2; horz[1]=0; vert[0]=0; vert[1]=(float)m_Point2DSize-scalardiff*2; // now paint text if available if (dynamic_cast(this->GetDataNode() ->GetProperty("label")) != NULL) { const char * pointLabel = dynamic_cast( this->GetDataNode()->GetProperty("label"))->GetValue(); std::string l = pointLabel; if (input->GetSize()>1) { // char buffer[20]; // sprintf(buffer,"%d",it->Index()); std::stringstream ss; ss << it->Index(); l.append(ss.str()); } if (unselectedColor != NULL) { mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); float rgb[3];//yellow rgb[0] = unselectedColor[0]; rgb[1] = unselectedColor[1]; rgb[2] = unselectedColor[2]; OpenGLrenderer->WriteSimpleText(l, pt2d[0] + text2dDistance, pt2d[1] + text2dDistance,rgb[0], rgb[1],rgb[2]); } else { mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); OpenGLrenderer->WriteSimpleText(l, pt2d[0] + text2dDistance, pt2d[1] + text2dDistance,0.0,1.0,0.0); } } if((m_ShowPoints) && ( (m_ShowDistantPoints && scalardiff<4.0) || (!m_ShowDistantPoints && scalardiff < scalarDiffTolerance) ) ) { //check if the point is to be marked as selected if(selIt != selEnd || pointDataBroken) { bool addAsSelected = false; if (pointDataBroken) addAsSelected = false; else if (selIt->Value().selected) addAsSelected = true; else addAsSelected = false; if (addAsSelected) { horz[0]=(float)m_Point2DSize; vert[1]=(float)m_Point2DSize; glColor3f(selectedColor[0],selectedColor[1],selectedColor[2]); glLineWidth(m_PointLineWidth); //a diamond around the point with the selected color glBegin (GL_LINE_LOOP); tmp=pt2d-horz; glVertex2fv(&tmp[0]); tmp=pt2d+vert; glVertex2fv(&tmp[0]); tmp=pt2d+horz; glVertex2fv(&tmp[0]); tmp=pt2d-vert; glVertex2fv(&tmp[0]); glEnd (); glLineWidth(1); //the actual point in the specified color to see the usual color of the point glColor3f(unselectedColor[0],unselectedColor[1],unselectedColor[2]); glPointSize(1); glBegin (GL_POINTS); tmp=pt2d; glVertex2fv(&tmp[0]); glEnd (); } else //if not selected { glColor3f(unselectedColor[0],unselectedColor[1],unselectedColor[2]); glLineWidth(m_PointLineWidth); //drawing crosses glBegin (GL_LINES); tmp=pt2d-horz; glVertex2fv(&tmp[0]); tmp=pt2d+horz; glVertex2fv(&tmp[0]); tmp=pt2d-vert; glVertex2fv(&tmp[0]); tmp=pt2d+vert; glVertex2fv(&tmp[0]); glEnd (); glLineWidth(1); } } } bool drawLinesEtc = true; if (!m_ShowDistantLines && counter > 0) // check, whether this line should be drawn { ScalarType currentDistance = displayGeometry->GetWorldGeometry()->SignedDistance(p); ScalarType lastDistance = displayGeometry->GetWorldGeometry()->SignedDistance(lastP); if ( currentDistance * lastDistance > 0.5 ) // points on same side of plane drawLinesEtc = false; } // draw a line if ((m_Polygon && counter>0 && drawLinesEtc) || (m_Polygon && m_PolygonClosed && drawLinesEtc)) { if ((counter == 0) && ( m_PolygonClosed)) { lastPt2d = lastPt2DInPointSet; } //get contour color property float contourColor[4] = {unselectedColor[0], unselectedColor[1], unselectedColor[2], unselectedColor[3]};//so if no property set, then use unselected color if (dynamic_cast(node->GetPropertyList(renderer)->GetProperty("contourcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor"))->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } else if (dynamic_cast(node->GetPropertyList(NULL)->GetProperty("contourcolor")) != NULL) { mitk::Color tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor"))->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } //set this color glColor3f(contourColor[0],contourColor[1],contourColor[2]); glLineWidth( m_LineWidth ); glBegin (GL_LINES); glVertex2fv(&pt2d[0]); glVertex2fv(&lastPt2d[0]); glEnd (); glLineWidth(1.0); if(m_ShowDistances) // calculate and print a distance { std::stringstream buffer; float distance = vec.GetNorm(); buffer<( renderer ); OpenGLrenderer->WriteSimpleText(buffer.str(), pos2d[0], pos2d[1]); //this->WriteTextXY(pos2d[0], pos2d[1], buffer.str(),renderer); } if(m_ShowAngles && counter > 1 ) // calculate and print the angle btw. two lines { std::stringstream buffer; //buffer << angle(vec.Get_vnl_vector(), -lastVec.Get_vnl_vector())*180/vnl_math::pi << "�"; buffer << angle(vec.Get_vnl_vector(), -lastVec.Get_vnl_vector())*180/vnl_math::pi << (char)176; Vector2D vec2d = pt2d-lastPt2d; vec2d.Normalize(); Vector2D lastVec2d = lastPt2d-preLastPt2d; lastVec2d.Normalize(); vec2d=vec2d-lastVec2d; vec2d.Normalize(); Vector2D pos2d = lastPt2d.GetVectorFromOrigin()+vec2d*text2dDistance*text2dDistance; mitk::VtkPropRenderer* OpenGLrenderer = dynamic_cast( renderer ); OpenGLrenderer->WriteSimpleText(buffer.str(), pos2d[0], pos2d[1]); //this->WriteTextXY(pos2d[0], pos2d[1], buffer.str(),renderer); } } counter++; } ++it; if(selIt != selEnd && !pointDataBroken) ++selIt; j++; } //recall the color to the same color before this drawing glColor3f(recallColor[0],recallColor[1],recallColor[2]); } } void mitk::PointSetGLMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "line width", mitk::IntProperty::New(2), renderer, overwrite ); // width of the line from one point to another node->AddProperty( "point line width", mitk::IntProperty::New(1), renderer, overwrite ); //width of the cross marking a point node->AddProperty( "point 2D size", mitk::IntProperty::New(8), renderer, overwrite ); // length of the cross marking a point // length of an edge of the box marking a point node->AddProperty( "show contour", mitk::BoolProperty::New(false), renderer, overwrite ); // contour of the line between points node->AddProperty( "close contour", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "show points", mitk::BoolProperty::New(true), renderer, overwrite ); //show or hide points node->AddProperty( "show distances", mitk::BoolProperty::New(false), renderer, overwrite ); //show or hide distance measure (not always available) node->AddProperty( "distance decimal digits", mitk::IntProperty::New(2), renderer, overwrite ); //set the number of decimal digits to be shown node->AddProperty( "show angles", mitk::BoolProperty::New(false), renderer, overwrite ); //show or hide angle measurement (not always available) node->AddProperty( "show distant lines", mitk::BoolProperty::New(false), renderer, overwrite ); //show the line between to points from a distant view (equals "always on top" option) node->AddProperty( "show distant points", mitk::BoolProperty::New(true), renderer, overwrite ); //show the point when at a certain distance above/below the 2D imaging plane. node->AddProperty( "layer", mitk::IntProperty::New(1), renderer, overwrite ); // default to draw pointset above images (they have a default layer of 0) Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Core/Code/Rendering/mitkPointSetGLMapper2D.h b/Core/Code/Rendering/mitkPointSetGLMapper2D.h index ebabda5fa0..eae74025f8 100644 --- a/Core/Code/Rendering/mitkPointSetGLMapper2D.h +++ b/Core/Code/Rendering/mitkPointSetGLMapper2D.h @@ -1,95 +1,95 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKPointSetMAPPER2D_H_HEADER_INCLUDED #define MITKPointSetMAPPER2D_H_HEADER_INCLUDED #include -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" namespace mitk { class BaseRenderer; class PointSet; /** * @brief OpenGL-based mapper to display a mitk::PointSet in a 2D window. * * This mapper can actually more than just draw a number of points of a * mitk::PointSet. If you set the right properties of the mitk::DataNode, * which contains the point set, then this mapper will also draw lines * connecting the points, and calculate and display distances and angles * between adjacent points. Here is a complete list of boolean properties, * which might be of interest: * * - \b "show contour": Draw not only the points but also the connections between * them (default false) * - \b "line width": IntProperty which gives the width of the contour lines * - \b "show points": Wheter or not to draw the actual points (default true) * - \b "show distances": Wheter or not to calculate and print the distance * between adjacent points (default false) * - \b "show angles": Wheter or not to calculate and print the angle between * adjacent points (default false) * - \b "show distant lines": When true, the mapper will also draw contour * lines that are far away form the current slice (default true) * - \b "label": StringProperty with a label for this point set * * BUG 1321 - possible new features: * point-2d-size (length of lines in cross/diamond) * point-linewidth * * @ingroup Mapper */ -class MITK_CORE_EXPORT PointSetGLMapper2D : public GLMapper2D +class MITK_CORE_EXPORT PointSetGLMapper2D : public GLMapper { public: - mitkClassMacro(PointSetGLMapper2D, GLMapper2D); + mitkClassMacro(PointSetGLMapper2D, GLMapper); itkNewMacro(Self); /** @brief Get the PointDataList to map */ virtual const mitk::PointSet * GetInput(void); virtual void Paint(mitk::BaseRenderer * renderer); - virtual void ApplyProperties(mitk::BaseRenderer* renderer); + virtual void ApplyAllProperties(mitk::BaseRenderer* renderer); static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); protected: PointSetGLMapper2D(); virtual ~PointSetGLMapper2D(); bool m_Polygon; bool m_PolygonClosed; bool m_ShowPoints; bool m_ShowDistances; int m_DistancesDecimalDigits; bool m_ShowAngles; bool m_ShowDistantLines; int m_LineWidth; int m_PointLineWidth; int m_Point2DSize; bool m_ShowDistantPoints; }; } // namespace mitk #endif /* MITKPointSetMapper2D_H_HEADER_INCLUDED */ diff --git a/Core/Code/Rendering/mitkPointSetVtkMapper3D.cpp b/Core/Code/Rendering/mitkPointSetVtkMapper3D.cpp index 7e7c09fe5c..4e8f3b8c3d 100644 --- a/Core/Code/Rendering/mitkPointSetVtkMapper3D.cpp +++ b/Core/Code/Rendering/mitkPointSetVtkMapper3D.cpp @@ -1,628 +1,624 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPointSetVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkColorProperty.h" #include "mitkVtkPropRenderer.h" #include "mitkPointSet.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const mitk::PointSet* mitk::PointSetVtkMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } mitk::PointSetVtkMapper3D::PointSetVtkMapper3D() : m_vtkSelectedPointList(NULL), m_vtkUnselectedPointList(NULL), m_VtkSelectedPolyDataMapper(NULL), m_VtkUnselectedPolyDataMapper(NULL), m_vtkTextList(NULL), m_NumberOfSelectedAdded(0), m_NumberOfUnselectedAdded(0), m_PointSize(1.0), m_ContourRadius(0.5) { //propassembly m_PointsAssembly = vtkSmartPointer::New(); //creating actors to be able to set transform m_SelectedActor = vtkSmartPointer::New(); m_UnselectedActor = vtkSmartPointer::New(); m_ContourActor = vtkSmartPointer::New(); } mitk::PointSetVtkMapper3D::~PointSetVtkMapper3D() { } void mitk::PointSetVtkMapper3D::ReleaseGraphicsResources(vtkWindow *renWin) { m_PointsAssembly->ReleaseGraphicsResources(renWin); m_SelectedActor->ReleaseGraphicsResources(renWin); m_UnselectedActor->ReleaseGraphicsResources(renWin); m_ContourActor->ReleaseGraphicsResources(renWin); } + void mitk::PointSetVtkMapper3D::CreateVTKRenderObjects() { m_vtkSelectedPointList = vtkSmartPointer::New(); m_vtkUnselectedPointList = vtkSmartPointer::New(); m_PointsAssembly->VisibilityOn(); if(m_PointsAssembly->GetParts()->IsItemPresent(m_SelectedActor)) m_PointsAssembly->RemovePart(m_SelectedActor); if(m_PointsAssembly->GetParts()->IsItemPresent(m_UnselectedActor)) m_PointsAssembly->RemovePart(m_UnselectedActor); if(m_PointsAssembly->GetParts()->IsItemPresent(m_ContourActor)) m_PointsAssembly->RemovePart(m_ContourActor); // exceptional displaying for PositionTracker -> MouseOrientationTool int mapperID; bool isInputDevice=false; if( this->GetDataNode()->GetBoolProperty("inputdevice",isInputDevice) && isInputDevice ) { if( this->GetDataNode()->GetIntProperty("BaseRendererMapperID",mapperID) && mapperID == 2) return; //The event for the PositionTracker came from the 3d widget and not needs to be displayed } // get and update the PointSet mitk::PointSet::Pointer input = const_cast(this->GetInput()); /* only update the input data, if the property tells us to */ bool update = true; this->GetDataNode()->GetBoolProperty("updateDataOnRender", update); if (update == true) input->Update(); int timestep = this->GetTimestep(); mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet( timestep ); if ( itkPointSet.GetPointer() == NULL) { m_PointsAssembly->VisibilityOff(); return; } mitk::PointSet::PointsContainer::Iterator pointsIter; mitk::PointSet::PointDataContainer::Iterator pointDataIter; int j; m_NumberOfSelectedAdded = 0; m_NumberOfUnselectedAdded = 0; //create contour bool makeContour = false; this->GetDataNode()->GetBoolProperty("show contour", makeContour); if (makeContour) { this->CreateContour(); } //now fill selected and unselected pointList //get size of Points in Property m_PointSize = 2; mitk::FloatProperty::Pointer pointSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("pointsize")); if ( pointSizeProp.IsNotNull() ) m_PointSize = pointSizeProp->GetValue(); //get the property for creating a label onto every point only once bool showLabel = true; this->GetDataNode()->GetBoolProperty("show label", showLabel); const char * pointLabel=NULL; if(showLabel) { if(dynamic_cast(this->GetDataNode()->GetPropertyList()->GetProperty("label")) != NULL) pointLabel =dynamic_cast(this->GetDataNode()->GetPropertyList()->GetProperty("label"))->GetValue(); else showLabel = false; } //check if the list for the PointDataContainer is the same size as the PointsContainer. Is not, then the points were inserted manually and can not be visualized according to the PointData (selected/unselected) bool pointDataBroken = (itkPointSet->GetPointData()->Size() != itkPointSet->GetPoints()->Size()); //now add an object for each point in data pointDataIter = itkPointSet->GetPointData()->Begin(); for (j=0, pointsIter=itkPointSet->GetPoints()->Begin(); pointsIter!=itkPointSet->GetPoints()->End(); pointsIter++, j++) { //check for the pointtype in data and decide which geom-object to take and then add to the selected or unselected list int pointType; if(itkPointSet->GetPointData()->size() == 0 || pointDataBroken) pointType = mitk::PTUNDEFINED; else pointType = pointDataIter.Value().pointSpec; vtkSmartPointer source; switch (pointType) { case mitk::PTUNDEFINED: { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(m_PointSize); itk::Point point1 = pointsIter->Value(); sphere->SetCenter(point1[0],point1[1],point1[2]); //sphere->SetCenter(pointsIter.Value()[0],pointsIter.Value()[1],pointsIter.Value()[2]); //MouseOrientation Tool (PositionTracker) if(isInputDevice) { sphere->SetThetaResolution(10); sphere->SetPhiResolution(10); } else { sphere->SetThetaResolution(20); sphere->SetPhiResolution(20); } source = sphere; } break; case mitk::PTSTART: { vtkSmartPointer cube = vtkSmartPointer::New(); cube->SetXLength(m_PointSize/2); cube->SetYLength(m_PointSize/2); cube->SetZLength(m_PointSize/2); itk::Point point1 = pointsIter->Value(); cube->SetCenter(point1[0],point1[1],point1[2]); source = cube; } break; case mitk::PTCORNER: { vtkSmartPointer cone = vtkSmartPointer::New(); cone->SetRadius(m_PointSize); itk::Point point1 = pointsIter->Value(); cone->SetCenter(point1[0],point1[1],point1[2]); cone->SetResolution(20); source = cone; } break; case mitk::PTEDGE: { vtkSmartPointer cylinder = vtkSmartPointer::New(); cylinder->SetRadius(m_PointSize); itk::Point point1 = pointsIter->Value(); cylinder->SetCenter(point1[0],point1[1],point1[2]); cylinder->SetResolution(20); source = cylinder; } break; case mitk::PTEND: { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(m_PointSize); //itk::Point point1 = pointsIter->Value(); sphere->SetThetaResolution(20); sphere->SetPhiResolution(20); source = sphere; } break; default: { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(m_PointSize); itk::Point point1 = pointsIter->Value(); sphere->SetCenter(point1[0],point1[1],point1[2]); sphere->SetThetaResolution(20); sphere->SetPhiResolution(20); source = sphere; } break; } if (!pointDataBroken) { if (pointDataIter.Value().selected) { m_vtkSelectedPointList->AddInput(source->GetOutput()); ++m_NumberOfSelectedAdded; } else { m_vtkUnselectedPointList->AddInput(source->GetOutput()); ++m_NumberOfUnselectedAdded; } } else { m_vtkUnselectedPointList->AddInput(source->GetOutput()); ++m_NumberOfUnselectedAdded; } if (showLabel) { char buffer[20]; std::string l = pointLabel; if ( input->GetSize()>1 ) { sprintf(buffer,"%d",j+1); l.append(buffer); } // Define the text for the label vtkSmartPointer label = vtkSmartPointer::New(); label->SetText(l.c_str()); //# Set up a transform to move the label to a new position. vtkSmartPointer aLabelTransform = vtkSmartPointer::New(); aLabelTransform->Identity(); itk::Point point1 = pointsIter->Value(); aLabelTransform->Translate(point1[0]+2,point1[1]+2,point1[2]); aLabelTransform->Scale(5.7,5.7,5.7); //# Move the label to a new position. vtkSmartPointer labelTransform = vtkSmartPointer::New(); labelTransform->SetTransform(aLabelTransform); labelTransform->SetInput(label->GetOutput()); //add it to the wright PointList if (pointType) { m_vtkSelectedPointList->AddInput(labelTransform->GetOutput()); ++m_NumberOfSelectedAdded; } else { m_vtkUnselectedPointList->AddInput(labelTransform->GetOutput()); ++m_NumberOfUnselectedAdded; } } if(pointDataIter != itkPointSet->GetPointData()->End()) pointDataIter++; } // end FOR //now according to number of elements added to selected or unselected, build up the rendering pipeline if (m_NumberOfSelectedAdded > 0) { m_VtkSelectedPolyDataMapper = vtkSmartPointer::New(); m_VtkSelectedPolyDataMapper->SetInput(m_vtkSelectedPointList->GetOutput()); //create a new instance of the actor m_SelectedActor = vtkSmartPointer::New(); m_SelectedActor->SetMapper(m_VtkSelectedPolyDataMapper); m_PointsAssembly->AddPart(m_SelectedActor); } if (m_NumberOfUnselectedAdded > 0) { m_VtkUnselectedPolyDataMapper = vtkSmartPointer::New(); m_VtkUnselectedPolyDataMapper->SetInput(m_vtkUnselectedPointList->GetOutput()); //create a new instance of the actor m_UnselectedActor = vtkSmartPointer::New(); m_UnselectedActor->SetMapper(m_VtkUnselectedPolyDataMapper); m_PointsAssembly->AddPart(m_UnselectedActor); } } -void mitk::PointSetVtkMapper3D::GenerateData() +void mitk::PointSetVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { - //create new vtk render objects (e.g. sphere for a point) + // create new vtk render objects (e.g. sphere for a point) this->CreateVTKRenderObjects(); - //apply props - this->ApplyProperties(m_ContourActor,NULL); - -} - - -void mitk::PointSetVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) -{ SetVtkMapperImmediateModeRendering(m_VtkSelectedPolyDataMapper); SetVtkMapperImmediateModeRendering(m_VtkUnselectedPolyDataMapper); mitk::FloatProperty::Pointer pointSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("pointsize")); mitk::FloatProperty::Pointer contourSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("contoursize")); // only create new vtk render objects if property values were changed if ( pointSizeProp.IsNotNull() && contourSizeProp.IsNotNull() ) { if (m_PointSize!=pointSizeProp->GetValue() || m_ContourRadius!= contourSizeProp->GetValue()) { this->CreateVTKRenderObjects(); } } - this->ApplyProperties(m_ContourActor,renderer); + this->ApplyAllProperties(renderer, m_ContourActor); - if(IsVisible(renderer)==false) + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + if(!visible) { m_UnselectedActor->VisibilityOff(); m_SelectedActor->VisibilityOff(); m_ContourActor->VisibilityOff(); return; } bool showPoints = true; this->GetDataNode()->GetBoolProperty("show points", showPoints); if(showPoints) { m_UnselectedActor->VisibilityOn(); m_SelectedActor->VisibilityOn(); } else { m_UnselectedActor->VisibilityOff(); m_SelectedActor->VisibilityOff(); } if(dynamic_cast(this->GetDataNode()->GetProperty("opacity")) != NULL) { mitk::FloatProperty::Pointer pointOpacity =dynamic_cast(this->GetDataNode()->GetProperty("opacity")); float opacity = pointOpacity->GetValue(); m_ContourActor->GetProperty()->SetOpacity(opacity); m_UnselectedActor->GetProperty()->SetOpacity(opacity); m_SelectedActor->GetProperty()->SetOpacity(opacity); } bool makeContour = false; this->GetDataNode()->GetBoolProperty("show contour", makeContour); if (makeContour) { m_ContourActor->VisibilityOn(); } else { m_ContourActor->VisibilityOff(); } } void mitk::PointSetVtkMapper3D::ResetMapper( BaseRenderer* /*renderer*/ ) { m_PointsAssembly->VisibilityOff(); } vtkProp* mitk::PointSetVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) { return m_PointsAssembly; } void mitk::PointSetVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) { vtkSmartPointer vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); m_SelectedActor->SetUserTransform(vtktransform); m_UnselectedActor->SetUserTransform(vtktransform); m_ContourActor->SetUserTransform(vtktransform); } -void mitk::PointSetVtkMapper3D::ApplyProperties(vtkActor* actor, mitk::BaseRenderer* renderer) +void mitk::PointSetVtkMapper3D::ApplyAllProperties(mitk::BaseRenderer* renderer, vtkActor* actor) { - Superclass::ApplyProperties(actor,renderer); + Superclass::ApplyColorAndOpacityProperties(renderer, actor); //check for color props and use it for rendering of selected/unselected points and contour //due to different params in VTK (double/float) we have to convert! //vars to convert to vtkFloatingPointType unselectedColor[4]={1.0f,1.0f,0.0f,1.0f};//yellow vtkFloatingPointType selectedColor[4]={1.0f,0.0f,0.0f,1.0f};//red vtkFloatingPointType contourColor[4]={1.0f,0.0f,0.0f,1.0f};//red //different types for color!!! mitk::Color tmpColor; double opacity = 1.0; //check if there is an unselected property if (dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("unselectedcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("unselectedcolor"))->GetValue(); unselectedColor[0] = tmpColor[0]; unselectedColor[1] = tmpColor[1]; unselectedColor[2] = tmpColor[2]; unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value } else if (dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("unselectedcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("unselectedcolor"))->GetValue(); unselectedColor[0] = tmpColor[0]; unselectedColor[1] = tmpColor[1]; unselectedColor[2] = tmpColor[2]; unselectedColor[3] = 1.0f; //!!define a new ColorProp to be able to pass alpha value } else { //check if the node has a color float unselectedColorTMP[4]={1.0f,1.0f,0.0f,1.0f};//yellow m_DataNode->GetColor(unselectedColorTMP, NULL); unselectedColor[0] = unselectedColorTMP[0]; unselectedColor[1] = unselectedColorTMP[1]; unselectedColor[2] = unselectedColorTMP[2]; //unselectedColor[3] stays 1.0f } //get selected property if (dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("selectedcolor"))->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; } else if (dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("selectedcolor"))->GetValue(); selectedColor[0] = tmpColor[0]; selectedColor[1] = tmpColor[1]; selectedColor[2] = tmpColor[2]; selectedColor[3] = 1.0f; } //get contour property if (dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("contourcolor"))->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } else if (dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor")) != NULL) { tmpColor = dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("contourcolor"))->GetValue(); contourColor[0] = tmpColor[0]; contourColor[1] = tmpColor[1]; contourColor[2] = tmpColor[2]; contourColor[3] = 1.0f; } if(dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("opacity")) != NULL) { mitk::FloatProperty::Pointer pointOpacity =dynamic_cast(this->GetDataNode()->GetPropertyList(renderer)->GetProperty("opacity")); opacity = pointOpacity->GetValue(); } else if(dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("opacity")) != NULL) { mitk::FloatProperty::Pointer pointOpacity =dynamic_cast(this->GetDataNode()->GetPropertyList(NULL)->GetProperty("opacity")); opacity = pointOpacity->GetValue(); } //finished color / opacity fishing! //check if a contour shall be drawn bool makeContour = false; this->GetDataNode()->GetBoolProperty("show contour", makeContour, renderer); if(makeContour && (m_ContourActor != NULL) ) { this->CreateContour(); m_ContourActor->GetProperty()->SetColor(contourColor); m_ContourActor->GetProperty()->SetOpacity(opacity); } m_SelectedActor->GetProperty()->SetColor(selectedColor); m_SelectedActor->GetProperty()->SetOpacity(opacity); m_UnselectedActor->GetProperty()->SetColor(unselectedColor); m_UnselectedActor->GetProperty()->SetOpacity(opacity); } void mitk::PointSetVtkMapper3D::CreateContour() { vtkSmartPointer vtkContourPolyData = vtkSmartPointer::New(); vtkSmartPointer vtkContourPolyDataMapper = vtkSmartPointer::New(); vtkSmartPointer points = vtkSmartPointer::New(); vtkSmartPointer polys = vtkSmartPointer::New(); mitk::PointSet::PointsContainer::Iterator pointsIter; // mitk::PointSet::PointDataContainer::Iterator pointDataIter; int j; // get and update the PointSet mitk::PointSet::Pointer input = const_cast(this->GetInput()); int timestep = this->GetTimestep(); mitk::PointSet::DataType::Pointer itkPointSet = input->GetPointSet( timestep ); if ( itkPointSet.GetPointer() == NULL) { return; } for (j=0, pointsIter=itkPointSet->GetPoints()->Begin(); pointsIter!=itkPointSet->GetPoints()->End() ; pointsIter++,j++) { vtkIdType cell[2] = {j-1,j}; itk::Point point1 = pointsIter->Value(); points->InsertPoint(j,point1[0],point1[1],point1[2]); if (j>0) polys->InsertNextCell(2,cell); } bool close = false; this->GetDataNode()->GetBoolProperty("close contour", close); if (close) { vtkIdType cell[2] = {j-1,0}; polys->InsertNextCell(2,cell); } vtkSmartPointer contour = vtkSmartPointer::New(); contour->SetPoints(points); contour->SetLines(polys); contour->Update(); vtkSmartPointer tubeFilter = vtkSmartPointer::New(); tubeFilter->SetNumberOfSides( 12 ); tubeFilter->SetInput(contour); //check for property contoursize. m_ContourRadius = 0.5; mitk::FloatProperty::Pointer contourSizeProp = dynamic_cast(this->GetDataNode()->GetProperty("contoursize") ); if (contourSizeProp.IsNotNull()) m_ContourRadius = contourSizeProp->GetValue(); tubeFilter->SetRadius( m_ContourRadius ); tubeFilter->Update(); //add to pipeline vtkContourPolyData->AddInput(tubeFilter->GetOutput()); vtkContourPolyDataMapper->SetInput(vtkContourPolyData->GetOutput()); m_ContourActor->SetMapper(vtkContourPolyDataMapper); m_PointsAssembly->AddPart(m_ContourActor); } void mitk::PointSetVtkMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "line width", mitk::IntProperty::New(2), renderer, overwrite ); node->AddProperty( "pointsize", mitk::FloatProperty::New(1.0), renderer, overwrite); node->AddProperty( "selectedcolor", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite); //red node->AddProperty( "color", mitk::ColorProperty::New(1.0f, 1.0f, 0.0f), renderer, overwrite); //yellow + node->AddProperty( "opacity", mitk::FloatProperty::New(1.0f), renderer, overwrite ); node->AddProperty( "show contour", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "close contour", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "contourcolor", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite); node->AddProperty( "contoursize", mitk::FloatProperty::New(0.5), renderer, overwrite ); node->AddProperty( "show points", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "updateDataOnRender", mitk::BoolProperty::New(true), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Core/Code/Rendering/mitkPointSetVtkMapper3D.h b/Core/Code/Rendering/mitkPointSetVtkMapper3D.h index 1202fa2632..ffca0102c2 100644 --- a/Core/Code/Rendering/mitkPointSetVtkMapper3D.h +++ b/Core/Code/Rendering/mitkPointSetVtkMapper3D.h @@ -1,152 +1,151 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKPointSetVtkMAPPER3D_H_HEADER_INCLUDED_C1907273 #define MITKPointSetVtkMAPPER3D_H_HEADER_INCLUDED_C1907273 #include -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include "mitkBaseRenderer.h" #include class vtkActor; class vtkPropAssembly; class vtkAppendPolyData; class vtkPolyData; class vtkTubeFilter; class vtkPolyDataMapper; namespace mitk { class PointSet; /** * @brief Vtk-based mapper for PointSet * * Due to the need of different colors for selected * and unselected points and the facts, that we also have a contour and * labels for the points, the vtk structure is build up the following way: * * We have two AppendPolyData, one selected, and one unselected and one * for a contour between the points. Each one is connected to an own * PolyDaraMapper and an Actor. The different color for the unselected and * selected state and for the contour is read from properties. * * "unselectedcolor", "selectedcolor" and "contourcolor" are the strings, * that are looked for. Pointlabels are added besides the selected or the * deselected points. * * Then the three Actors are combined inside a vtkPropAssembly and this * object is returned in GetProp() and so hooked up into the rendering * pipeline. * Properties that can be set for point sets and influence the PointSetVTKMapper3D are: * * - \b "color": (ColorProperty*) Color of the point set * - \b "Opacity": (FloatProperty) Opacity of the point set * - \b "show contour": (BoolProperty) If the contour of the points are visible * - \b "contourSizeProp":(FloatProperty) Contour size of the points The default properties are: * - \b "line width": (IntProperty::New(2), renderer, overwrite ) * - \b "pointsize": (FloatProperty::New(1.0), renderer, overwrite) * - \b "selectedcolor": (ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite) //red * - \b "color": (ColorProperty::New(1.0f, 1.0f, 0.0f), renderer, overwrite) //yellow * - \b "show contour": (BoolProperty::New(false), renderer, overwrite ) * - \b "contourcolor": (ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite) * - \b "contoursize": (FloatProperty::New(0.5), renderer, overwrite ) * - \b "close contour": (BoolProperty::New(false), renderer, overwrite ) * - \b "show points": (BoolProperty::New(true), renderer, overwrite ) * - \b "updateDataOnRender": (BoolProperty::New(true), renderer, overwrite ) *Other properties looked for are: * * - \b "show contour": if set to on, lines between the points are shown * - \b "close contour": if set to on, the open strip is closed (first point * connected with last point) * - \b "pointsize": size of the points mapped * - \b "label": text of the Points to show besides points * - \b "contoursize": size of the contour drawn between the points * (if not set, the pointsize is taken) * * @ingroup Mapper */ - class MITK_CORE_EXPORT PointSetVtkMapper3D : public VtkMapper3D + class MITK_CORE_EXPORT PointSetVtkMapper3D : public VtkMapper { public: - mitkClassMacro(PointSetVtkMapper3D, VtkMapper3D); + mitkClassMacro(PointSetVtkMapper3D, VtkMapper); itkNewMacro(Self); virtual const mitk::PointSet* GetInput(); //overwritten from VtkMapper3D to be able to return a //m_PointsAssembly which is much faster than a vtkAssembly virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); virtual void UpdateVtkTransform(mitk::BaseRenderer* renderer); static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); void ReleaseGraphicsResources(vtkWindow *renWin); protected: PointSetVtkMapper3D(); virtual ~PointSetVtkMapper3D(); - virtual void GenerateData(); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); virtual void ResetMapper( BaseRenderer* renderer ); - virtual void ApplyProperties(vtkActor* actor, mitk::BaseRenderer* renderer); + virtual void ApplyAllProperties(mitk::BaseRenderer* renderer, vtkActor* actor); virtual void CreateContour(); virtual void CreateVTKRenderObjects(); vtkSmartPointer m_vtkSelectedPointList; vtkSmartPointer m_vtkUnselectedPointList; vtkSmartPointer m_VtkSelectedPolyDataMapper; vtkSmartPointer m_VtkUnselectedPolyDataMapper; vtkSmartPointer m_SelectedActor; vtkSmartPointer m_UnselectedActor; vtkSmartPointer m_ContourActor; vtkSmartPointer m_PointsAssembly; //help for contour between points vtkSmartPointer m_vtkTextList; //variables to be able to log, how many inputs have been added to PolyDatas unsigned int m_NumberOfSelectedAdded; unsigned int m_NumberOfUnselectedAdded; //variables to check if an update of the vtk objects is needed ScalarType m_PointSize; ScalarType m_ContourRadius; }; } // namespace mitk #endif /* MITKPointSetVtkMAPPER3D_H_HEADER_INCLUDED_C1907273 */ diff --git a/Core/Code/Rendering/mitkPolyDataGLMapper2D.cpp b/Core/Code/Rendering/mitkPolyDataGLMapper2D.cpp index caadd84073..920d51fec2 100644 --- a/Core/Code/Rendering/mitkPolyDataGLMapper2D.cpp +++ b/Core/Code/Rendering/mitkPolyDataGLMapper2D.cpp @@ -1,274 +1,276 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkPolyDataGLMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkSurface.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkAbstractTransformGeometry.h" #include "mitkVtkMapper3D.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void mitk::PolyDataGLMapper2D::Paint( mitk::BaseRenderer * renderer ) { - if ( IsVisible( renderer ) == false ) - return ; + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible ) return; // ok, das ist aus GenerateData kopiert - mitk::BaseData::Pointer input = const_cast( GetData() ); + mitk::BaseData::Pointer input = const_cast( GetDataNode()->GetData() ); assert( input ); input->Update(); vtkPolyData * vtkpolydata = this->GetVtkPolyData(); assert( vtkpolydata ); vtkLinearTransform * vtktransform = GetDataNode() ->GetVtkTransform(); if (vtktransform) { vtkLinearTransform * inversetransform = vtktransform->GetLinearInverse(); Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); if ( vtkpolydata != NULL ) { Point3D point; Vector3D normal; if(worldPlaneGeometry.IsNotNull()) { // set up vtkPlane according to worldGeometry point=worldPlaneGeometry->GetOrigin(); normal=worldPlaneGeometry->GetNormal(); normal.Normalize(); m_Plane->SetTransform((vtkAbstractTransform*)NULL); } else { //@FIXME: does not work correctly. Does m_Plane->SetTransform really transforms a "plane plane" into a "curved plane"? return; AbstractTransformGeometry::ConstPointer worldAbstractGeometry = dynamic_cast(renderer->GetCurrentWorldGeometry2D()); if(worldAbstractGeometry.IsNotNull()) { // set up vtkPlane according to worldGeometry point=const_cast(worldAbstractGeometry->GetParametricBoundingBox())->GetMinimum(); FillVector3D(normal, 0, 0, 1); m_Plane->SetTransform(worldAbstractGeometry->GetVtkAbstractTransform()->GetInverse()); } else return; } vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; vnl2vtk(point.Get_vnl_vector(), vp); vnl2vtk(normal.Get_vnl_vector(), vnormal); //normally, we would need to transform the surface and cut the transformed surface with the cutter. //This might be quite slow. Thus, the idea is, to perform an inverse transform of the plane instead. //@todo It probably does not work for scaling operations yet:scaling operations have to be //dealed with after the cut is performed by scaling the contour. inversetransform->TransformPoint( vp, vp ); inversetransform->TransformNormalAtPoint( vp, vnormal, vnormal ); m_Plane->SetOrigin( vp ); m_Plane->SetNormal( vnormal ); // set data into cutter m_Cutter->SetInput( vtkpolydata ); // m_Cutter->GenerateCutScalarsOff(); // m_Cutter->SetSortByToSortByCell(); // calculate the cut m_Cutter->Update(); // fetch geometry mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert( displayGeometry ); // float toGL=displayGeometry->GetSizeInDisplayUnits()[1]; //apply color and opacity read from the PropertyList - ApplyProperties( renderer ); + ApplyColorAndOpacityProperties( renderer ); // traverse the cut contour vtkPolyData * contour = m_Cutter->GetOutput(); vtkPoints *vpoints = contour->GetPoints(); vtkCellArray *vpolys = contour->GetLines(); vtkPointData *vpointdata = contour->GetPointData(); vtkDataArray* vscalars = vpointdata->GetScalars(); vtkCellData *vcelldata = contour->GetCellData(); vtkDataArray* vcellscalars = vcelldata->GetScalars(); int i, numberOfCells = vpolys->GetNumberOfCells(); Point3D p; Point2D p2d, last, first; vpolys->InitTraversal(); vtkScalarsToColors* lut = GetVtkLUT(); assert ( lut != NULL ); for ( i = 0;i < numberOfCells;++i ) { vtkIdType *cell(NULL); vtkIdType cellSize(0); vpolys->GetNextCell( cellSize, cell ); if ( m_ColorByCellData ) { // color each cell according to cell data vtkFloatingPointType* color = lut->GetColor( vcellscalars->GetComponent( i, 0 ) ); glColor3f( color[ 0 ], color[ 1 ], color[ 2 ] ); } if ( m_ColorByPointData ) { vtkFloatingPointType* color = lut->GetColor( vscalars->GetComponent( cell[0], 0 ) ); glColor3f( color[ 0 ], color[ 1 ], color[ 2 ] ); } glBegin ( GL_LINE_LOOP ); for ( int j = 0;j < cellSize;++j ) { vpoints->GetPoint( cell[ j ], vp ); //take transformation via vtktransform into account vtktransform->TransformPoint( vp, vp ); vtk2itk( vp, p ); //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map( p, p2d ); //convert point (until now mm and in worldcoordinates) to display coordinates (units ) displayGeometry->WorldToDisplay( p2d, p2d ); //convert display coordinates ( (0,0) is top-left ) in GL coordinates ( (0,0) is bottom-left ) //p2d[1]=toGL-p2d[1]; //add the current vertex to the line glVertex2f( p2d[0], p2d[1] ); } glEnd (); } } } } vtkPolyDataMapper* mitk::PolyDataGLMapper2D::GetVtkPolyDataMapper() { return NULL; /* mitk::DataNode::ConstPointer node = this->GetDataNode(); if ( node.IsNull() ) return NULL; mitk::VtkMapper3D::Pointer mitkMapper = dynamic_cast< mitk::VtkMapper3D* > ( node->GetMapper( 2 ) ); if ( mitkMapper.IsNull() ) return NULL; mitkMapper->Update(NULL); vtkActor* actor = dynamic_cast( mitkMapper->GetVtkProp(0) ); if ( actor == NULL ) return NULL; return dynamic_cast( actor->GetMapper() ); */ } vtkPolyData* mitk::PolyDataGLMapper2D::GetVtkPolyData( ) { vtkPolyDataMapper * polyDataMapper = GetVtkPolyDataMapper(); if ( polyDataMapper == NULL ) return NULL; else return polyDataMapper->GetInput(); } vtkScalarsToColors* mitk::PolyDataGLMapper2D::GetVtkLUT( ) { vtkPolyDataMapper * polyDataMapper = GetVtkPolyDataMapper(); if ( polyDataMapper == NULL ) return NULL; else return polyDataMapper->GetLookupTable(); } bool mitk::PolyDataGLMapper2D::IsConvertibleToVtkPolyData() { return ( GetVtkPolyDataMapper() != NULL ); } mitk::PolyDataGLMapper2D::PolyDataGLMapper2D() { m_Plane = vtkPlane::New(); m_Cutter = vtkCutter::New(); m_Cutter->SetCutFunction( m_Plane ); m_Cutter->GenerateValues( 1, 0, 1 ); m_ColorByCellData = false; m_ColorByPointData = false; //m_LUT = vtkLookupTable::New(); //m_LUT->SetTableRange( 0, 255 ); //m_LUT->SetNumberOfColors( 255 ); //m_LUT->SetRampToLinear (); //m_LUT->Build(); } mitk::PolyDataGLMapper2D::~PolyDataGLMapper2D() {} diff --git a/Core/Code/Rendering/mitkPolyDataGLMapper2D.h b/Core/Code/Rendering/mitkPolyDataGLMapper2D.h index b68f386cd3..15307b96d3 100644 --- a/Core/Code/Rendering/mitkPolyDataGLMapper2D.h +++ b/Core/Code/Rendering/mitkPolyDataGLMapper2D.h @@ -1,109 +1,109 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MitkPolyDataGLMapper2D_H #define MitkPolyDataGLMapper2D_H #include -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" class vtkCutter; class vtkPlane; class vtkLookupTable; class vtkPolyData; class vtkScalarsToColors; class vtkPolyDataMapper; namespace mitk { class BaseRenderer; /** * @brief OpenGL-based mapper to display a 2d cut through a poly data * OpenGL-based mapper to display a 2D cut through a poly data. The result is * normally a line. This class can be added to any data object, which is * rendered in 3D via a vtkPolyData. */ -class MITK_CORE_EXPORT PolyDataGLMapper2D : public GLMapper2D +class MITK_CORE_EXPORT PolyDataGLMapper2D : public GLMapper { public: - mitkClassMacro( PolyDataGLMapper2D, GLMapper2D ); + mitkClassMacro( PolyDataGLMapper2D, GLMapper ); itkNewMacro( Self ); /** * Sets if the cut lines are colored by mapping cell data */ itkSetMacro( ColorByCellData, bool ); /** * Sets if the cut lines are colored by mapping point data */ itkSetMacro( ColorByPointData, bool ); /** * Renders a cut through a poly-data by lines. * @param renderer the render to render in. */ virtual void Paint( mitk::BaseRenderer * renderer ); protected: PolyDataGLMapper2D(); virtual ~PolyDataGLMapper2D(); /** * Determines, if the associated BaseData is mapped three-dimensionally (mapper-slot id 2) * with a class convertable to vtkPolyDataMapper(). * @returns NULL if it is not convertable or the appropriate PolyDataMapper otherwise */ virtual vtkPolyDataMapper* GetVtkPolyDataMapper(); /** * Determines the poly data object to be cut. * returns the poly data if possible, otherwise NULL. */ virtual vtkPolyData* GetVtkPolyData( ); /** * Determines the LookupTable used by the associated vtkMapper. * returns the LUT if possible, otherwise NULL. */ virtual vtkScalarsToColors* GetVtkLUT( ); /** * Checks if this mapper can be used to generate cuts through the associated * base data. * @return true if yes or false if not. */ virtual bool IsConvertibleToVtkPolyData(); vtkPlane* m_Plane; vtkCutter* m_Cutter; bool m_ColorByCellData; bool m_ColorByPointData; }; } // namespace mitk #endif /* MitkPolyDataGLMapper2D_H */ diff --git a/Core/Code/Testing/mitkRenderingTestHelper.cpp b/Core/Code/Rendering/mitkRenderingTestHelper.cpp similarity index 99% rename from Core/Code/Testing/mitkRenderingTestHelper.cpp rename to Core/Code/Rendering/mitkRenderingTestHelper.cpp index 49929a1c49..7f319a0130 100644 --- a/Core/Code/Testing/mitkRenderingTestHelper.cpp +++ b/Core/Code/Rendering/mitkRenderingTestHelper.cpp @@ -1,192 +1,191 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //VTK #include #include #include #include //MITK #include #include #include #include #include #include #include // include gl to read out properties #include #include mitkRenderingTestHelper::mitkRenderingTestHelper(int width, int height, int argc, char* argv[]) { // Global interaction must(!) be initialized mitk::GlobalInteraction::GetInstance()->Initialize("global"); m_DataStorage = mitk::StandaloneDataStorage::New(); m_RenderWindow = mitk::RenderWindow::New(); m_RenderWindow->GetRenderer()->SetDataStorage(m_DataStorage); m_RenderWindow->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D); this->GetVtkRenderWindow()->SetSize( width, height ); m_RenderWindow->GetRenderer()->Resize( width, height); //this->GetVtkRenderWindow()->DoubleBufferOff( ); this->SetInputFileNames(argc, argv); // prints the glinfo after creation of the vtkrenderwindow this->PrintGLInfo(); } mitkRenderingTestHelper::~mitkRenderingTestHelper() { } void mitkRenderingTestHelper::PrintGLInfo() { GLint maxTextureSize; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);; MITK_INFO << "OpenGL Render Context Information: \n" << "- GL_VENDOR: "<< glGetString(GL_VENDOR) << "\n" << "- GL_RENDERER: "<< glGetString(GL_RENDERER) << "\n" << "- GL_VERSION: "<< glGetString(GL_VERSION) << "\n" << "- GL_MAX_TEXTURE_SIZE: "<< maxTextureSize << "\n" << "- GL_EXTENSIONS: "<< glGetString(GL_EXTENSIONS); } void mitkRenderingTestHelper::SetMapperID( mitk::BaseRenderer::StandardMapperSlot id) { m_RenderWindow->GetRenderer()->SetMapperID(id); } void mitkRenderingTestHelper::Render() { //if the datastorage is initialized and at least 1 image is loaded render it if(m_DataStorage.IsNotNull() || m_DataStorage->GetAll()->Size() >= 1 ) { //perform global reinit: m_RenderWindow->GetRenderer()->PrepareRender(); // mitk::RenderingManager::GetInstance()->RequestUpdate(m_RenderWindow->GetVtkRenderWindow()); //use this to actually show the iamge in a renderwindow this->GetVtkRenderWindow()->Render(); // this->GetVtkRenderWindow()->GetInteractor()->Start(); } else { MITK_ERROR << "No images loaded in data storage!"; } } void mitkRenderingTestHelper::PrepareRender() { //perform global reinit: m_RenderWindow->GetRenderer()->PrepareRender(); } mitk::DataStorage::Pointer mitkRenderingTestHelper::GetDataStorage() { return m_DataStorage; } void mitkRenderingTestHelper::SetInputFileNames(int argc, char* argv[]) { // parse parameters for (int i = 1; i < argc; ++i) { //add everything to a list but -T and -V std::string tmp = argv[i]; if((tmp.compare("-T")) && (tmp.compare("-V"))) { this->AddToStorage(tmp); } else { break; } } } void mitkRenderingTestHelper::SetViewDirection(mitk::SliceNavigationController::ViewDirection viewDirection) { mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetSliceNavigationController()->SetDefaultViewDirection(viewDirection); mitk::RenderingManager::GetInstance()->InitializeViews( m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll()) ); } void mitkRenderingTestHelper::ReorientSlices(mitk::Point3D origin, mitk::Vector3D rotation) { mitk::SliceNavigationController::Pointer sliceNavigationController = mitk::BaseRenderer::GetInstance(m_RenderWindow->GetVtkRenderWindow())->GetSliceNavigationController(); sliceNavigationController->ReorientSlices(origin, rotation); } vtkRenderer* mitkRenderingTestHelper::GetVtkRenderer() { return m_RenderWindow->GetRenderer()->GetVtkRenderer(); } void mitkRenderingTestHelper::SetImageProperty(const char *propertyKey, mitk::BaseProperty* property ) { this->m_DataStorage->GetNode(mitk::NodePredicateDataType::New("Image"))->SetProperty(propertyKey, property); } vtkRenderWindow* mitkRenderingTestHelper::GetVtkRenderWindow() { return m_RenderWindow->GetVtkRenderWindow(); } //method to save a screenshot of the renderwindow (e.g. create a reference screenshot) void mitkRenderingTestHelper::SaveAsPNG(std::string fileName) { vtkSmartPointer renderer = this->GetVtkRenderer(); bool doubleBuffering( renderer->GetRenderWindow()->GetDoubleBuffer() ); renderer->GetRenderWindow()->DoubleBufferOff(); vtkSmartPointer magnifier = vtkSmartPointer::New(); magnifier->SetInput(renderer); magnifier->SetMagnification(1.0); vtkSmartPointer fileWriter = vtkSmartPointer::New(); fileWriter->SetInput(magnifier->GetOutput()); fileWriter->SetFileName(fileName.c_str()); fileWriter->Write(); renderer->GetRenderWindow()->SetDoubleBuffer(doubleBuffering); } void mitkRenderingTestHelper::AddToStorage(const std::string &filename) { try { mitk::DataNode::Pointer node = mitk::IOUtil::LoadDataNode(filename); this->AddNodeToStorage(node); } catch ( itk::ExceptionObject & e ) { MITK_ERROR << "Failed loading test data '" << filename << "': " << e.what(); } } void mitkRenderingTestHelper::AddNodeToStorage(mitk::DataNode::Pointer node) { this->m_DataStorage->Add(node); mitk::RenderingManager::GetInstance()->InitializeViews( m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll()) ); } - diff --git a/Core/Code/Testing/mitkRenderingTestHelper.h b/Core/Code/Rendering/mitkRenderingTestHelper.h similarity index 98% rename from Core/Code/Testing/mitkRenderingTestHelper.h rename to Core/Code/Rendering/mitkRenderingTestHelper.h index 4125932027..4b0ae508e1 100644 --- a/Core/Code/Testing/mitkRenderingTestHelper.h +++ b/Core/Code/Rendering/mitkRenderingTestHelper.h @@ -1,113 +1,114 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkRenderingTestHelper_h #define mitkRenderingTestHelper_h #include #include #include #include +#include + class vtkRenderWindow; class vtkRenderer; -class mitkRenderingTestHelper +class MITK_CORE_EXPORT mitkRenderingTestHelper { public: /** @brief Generate a rendering test helper object including a render window of the size width * height (in pixel). @param argc Number of parameters. (here: Images) "Usage: [filename1 filenam2 -V referenceScreenshot (optional -T /directory/to/save/differenceImage)] @param argv Given parameters. **/ mitkRenderingTestHelper(int width, int height, int argc, char *argv[]); ~mitkRenderingTestHelper(); /** @brief Getter for the vtkRenderer. **/ vtkRenderer* GetVtkRenderer(); /** @brief Getter for the vtkRenderWindow which should be used to call vtkRegressionTestImage. **/ vtkRenderWindow* GetVtkRenderWindow(); /** @brief Method can be used to save a screenshot (e.g. reference screenshot as a .png file. @param fileName The filename of the new screenshot (including path). **/ void SaveAsPNG(std::string fileName); /** @brief This method set the property of the member datastorage @param property Set a property for each image in the datastorage m_DataStorage. **/ void SetImageProperty(const char *propertyKey, mitk::BaseProperty *property); /** @brief Set the view direction of the renderwindow (e.g. sagittal, coronal, axial) **/ void SetViewDirection(mitk::SliceNavigationController::ViewDirection viewDirection); /** @brief Reorient the slice (e.g. rotation and translation like the swivel mode). **/ void ReorientSlices(mitk::Point3D origin, mitk::Vector3D rotation); /** @brief Render everything into an mitkRenderWindow. Call SetViewDirection() and SetProperty() before this method. **/ void Render(); /** @brief Calls PrepareRender function of mitkRenderWindow **/ void PrepareRender(); /** @brief Returns the datastorage, in order to modify the data inside a rendering test. **/ mitk::DataStorage::Pointer GetDataStorage(); /** * @brief SetMapperID Change between Standard2D and 3D mappers. * @param id Enum mitk::BaseRenderer::StandardMapperSlot which defines the mapper. */ void SetMapperID(mitk::BaseRenderer::StandardMapperSlot id); /** * @brief AddNodeToStorage Add a node to the datastorage and perform a reinit which is necessary for rendering. * @param node The data you want to add. */ void AddNodeToStorage(mitk::DataNode::Pointer node); protected: /** @brief Prints the opengl information, e.g. version, vendor and extensions, * This function can only be called after an opengl context is active. * It only prints the context after the vtkRenderwindow is fully initialized. **/ void PrintGLInfo(); /** @brief This method tries to load the given file into a member datastorage, in order to render it. @param fileName The filename of the file to be loaded (including path). **/ void AddToStorage(const std::string& filename); /** @brief This method tries to parse the given argv for files (e.g. images) and load them into a member datastorage, in order to render it. @param argc Number of parameters. @param argv Given parameters. **/ void SetInputFileNames(int argc, char *argv[]); mitk::RenderWindow::Pointer m_RenderWindow; //<< Contains the mitkRenderWindow into which the test renders the data mitk::DataStorage::Pointer m_DataStorage; //<< Contains the mitkDataStorage which contains the data to be rendered }; #endif - diff --git a/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp b/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp index 7a40fdbde9..06cac2223f 100644 --- a/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp +++ b/Core/Code/Rendering/mitkSurfaceGLMapper2D.cpp @@ -1,542 +1,544 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkSurfaceGLMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkSurface.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkVtkScalarModeProperty.h" #include "mitkAbstractTransformGeometry.h" #include "mitkLookupTableProperty.h" #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::SurfaceGLMapper2D::SurfaceGLMapper2D() : m_Plane( vtkPlane::New() ), m_Cutter( vtkCutter::New() ), m_LUT( vtkLookupTable::New() ), m_PointLocator( vtkPKdTree::New() ), m_Stripper( vtkStripper::New() ), m_DrawNormals(false), m_FrontNormalLengthInPixels(10.0), m_BackNormalLengthInPixels(10.0) { // default for normals on front side = green m_FrontSideColor[0] = 0.0; m_FrontSideColor[1] = 1.0; m_FrontSideColor[2] = 0.0; m_FrontSideColor[3] = 1.0; // default for normals on back side = red m_BackSideColor[0] = 1.0; m_BackSideColor[1] = 0.0; m_BackSideColor[2] = 0.0; m_BackSideColor[3] = 1.0; // default for line color = yellow m_LineColor[0] = 1.0; m_LineColor[1] = 1.0; m_LineColor[2] = 0.0; m_LineColor[3] = 1.0; m_Cutter->SetCutFunction(m_Plane); m_Cutter->GenerateValues(1,0,1); m_LUT->SetTableRange(0,255); m_LUT->SetNumberOfColors(255); m_LUT->SetRampToLinear(); m_LUT->Build(); } mitk::SurfaceGLMapper2D::~SurfaceGLMapper2D() { m_Plane->Delete(); m_Cutter->Delete(); m_LUT->Delete(); m_PointLocator->Delete(); m_Stripper->Delete(); } const mitk::Surface *mitk::SurfaceGLMapper2D::GetInput(void) { if(m_Surface.IsNotNull()) return m_Surface; - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } void mitk::SurfaceGLMapper2D::SetDataNode( mitk::DataNode* node ) { Superclass::SetDataNode( node ); bool useCellData; if (dynamic_cast(node->GetProperty("deprecated useCellDataForColouring")) == NULL) useCellData = false; else useCellData = dynamic_cast(node->GetProperty("deprecated useCellDataForColouring"))->GetValue(); if (!useCellData) { // search min/max point scalars over all time steps vtkFloatingPointType dataRange[2] = {0,0}; vtkFloatingPointType range[2]; Surface::Pointer input = const_cast< Surface* >(dynamic_cast( this->GetDataNode()->GetData() )); if(input.IsNull()) return; const TimeSlicedGeometry::Pointer inputTimeGeometry = input->GetTimeSlicedGeometry(); if(( inputTimeGeometry.IsNull() ) || ( inputTimeGeometry->GetTimeSteps() == 0 ) ) return; for (unsigned int timestep=0; timestepGetTimeSteps(); timestep++) { vtkPolyData * vtkpolydata = input->GetVtkPolyData( timestep ); if((vtkpolydata==NULL) || (vtkpolydata->GetNumberOfPoints() < 1 )) continue; vtkDataArray *vpointscalars = vtkpolydata->GetPointData()->GetScalars(); if (vpointscalars) { vpointscalars->GetRange( range, 0 ); if (dataRange[0]==0 && dataRange[1]==0) { dataRange[0] = range[0]; dataRange[1] = range[1]; } else { if (range[0] < dataRange[0]) dataRange[0] = range[0]; if (range[1] > dataRange[1]) dataRange[1] = range[1]; } } } if (dataRange[1] - dataRange[0] > 0) { m_LUT->SetTableRange( dataRange ); m_LUT->Build(); } } } void mitk::SurfaceGLMapper2D::Paint(mitk::BaseRenderer * renderer) { - if(IsVisible(renderer)==false) return; + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + if(!visible) return; Surface::Pointer input = const_cast(this->GetInput()); if(input.IsNull()) return; // // get the TimeSlicedGeometry of the input object // const TimeSlicedGeometry* inputTimeGeometry = input->GetTimeSlicedGeometry(); if(( inputTimeGeometry == NULL ) || ( inputTimeGeometry->GetTimeSteps() == 0 ) ) return; if (dynamic_cast(this->GetDataNode()->GetProperty("line width")) == NULL) m_LineWidth = 1; else m_LineWidth = dynamic_cast(this->GetDataNode()->GetProperty("line width"))->GetValue(); // // get the world time // Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); assert( worldGeometry.IsNotNull() ); ScalarType time = worldGeometry->GetTimeBounds()[ 0 ]; int timestep=0; if( time > ScalarTypeNumericTraits::NonpositiveMin() ) timestep = inputTimeGeometry->MSToTimeStep( time ); // int timestep = this->GetTimestep(); if( inputTimeGeometry->IsValidTime( timestep ) == false ) return; vtkPolyData * vtkpolydata = input->GetVtkPolyData( timestep ); if((vtkpolydata==NULL) || (vtkpolydata->GetNumberOfPoints() < 1 )) return; PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast(worldGeometry.GetPointer()); //apply color and opacity read from the PropertyList - ApplyProperties(renderer); + this->ApplyAllProperties(renderer); if (m_DrawNormals) { m_PointLocator->SetDataSet( vtkpolydata ); m_PointLocator->BuildLocatorFromPoints( vtkpolydata->GetPoints() ); } if(vtkpolydata!=NULL) { Point3D point; Vector3D normal; //Check if Lookup-Table is already given, else use standard one. vtkFloatingPointType* scalarLimits = m_LUT->GetTableRange(); vtkFloatingPointType scalarsMin = scalarLimits[0], scalarsMax = scalarLimits[1]; vtkLookupTable *lut;// = vtkLookupTable::New(); LookupTableProperty::Pointer lookupTableProp; this->GetDataNode()->GetProperty(lookupTableProp, "LookupTable", renderer); if (lookupTableProp.IsNotNull() ) { lut = lookupTableProp->GetLookupTable()->GetVtkLookupTable(); if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum")) != NULL) scalarsMin = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum"))->GetValue(); if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum")) != NULL) scalarsMax = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum"))->GetValue(); // check if the scalar range has been changed, e.g. manually, for the data tree node, and rebuild the LUT if necessary. double* oldRange = lut->GetTableRange(); if( oldRange[0] != scalarsMin || oldRange[1] != scalarsMax ) { lut->SetTableRange(scalarsMin, scalarsMax); lut->Build(); } } else { lut = m_LUT; } vtkLinearTransform * vtktransform = GetDataNode()->GetVtkTransform(timestep); if(worldPlaneGeometry.IsNotNull()) { // set up vtkPlane according to worldGeometry point=worldPlaneGeometry->GetOrigin(); normal=worldPlaneGeometry->GetNormal(); normal.Normalize(); m_Plane->SetTransform((vtkAbstractTransform*)NULL); } else { AbstractTransformGeometry::ConstPointer worldAbstractGeometry = dynamic_cast(renderer->GetCurrentWorldGeometry2D()); if(worldAbstractGeometry.IsNotNull()) { AbstractTransformGeometry::ConstPointer surfaceAbstractGeometry = dynamic_cast(input->GetTimeSlicedGeometry()->GetGeometry3D(0)); if(surfaceAbstractGeometry.IsNotNull()) //@todo substitude by operator== after implementation, see bug id 28 { PaintCells(renderer, vtkpolydata, worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut); return; } else { //@FIXME: does not work correctly. Does m_Plane->SetTransform really transforms a "flat plane" into a "curved plane"? return; // set up vtkPlane according to worldGeometry point=const_cast(worldAbstractGeometry->GetParametricBoundingBox())->GetMinimum(); FillVector3D(normal, 0, 0, 1); m_Plane->SetTransform(worldAbstractGeometry->GetVtkAbstractTransform()->GetInverse()); } } else return; } vtkFloatingPointType vp[3], vnormal[3]; vnl2vtk(point.Get_vnl_vector(), vp); vnl2vtk(normal.Get_vnl_vector(), vnormal); //normally, we would need to transform the surface and cut the transformed surface with the cutter. //This might be quite slow. Thus, the idea is, to perform an inverse transform of the plane instead. //@todo It probably does not work for scaling operations yet:scaling operations have to be //dealed with after the cut is performed by scaling the contour. vtkLinearTransform * inversetransform = vtktransform->GetLinearInverse(); inversetransform->TransformPoint(vp, vp); inversetransform->TransformNormalAtPoint(vp, vnormal, vnormal); m_Plane->SetOrigin(vp); m_Plane->SetNormal(vnormal); //set data into cutter m_Cutter->SetInput(vtkpolydata); m_Cutter->Update(); // m_Cutter->GenerateCutScalarsOff(); // m_Cutter->SetSortByToSortByCell(); if (m_DrawNormals) { m_Stripper->SetInput( m_Cutter->GetOutput() ); // calculate the cut m_Stripper->Update(); PaintCells(renderer, m_Stripper->GetOutput(), worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut, vtkpolydata); } else { PaintCells(renderer, m_Cutter->GetOutput(), worldGeometry, renderer->GetDisplayGeometry(), vtktransform, lut, vtkpolydata); } } } void mitk::SurfaceGLMapper2D::PaintCells(mitk::BaseRenderer* renderer, vtkPolyData* contour, const Geometry2D* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform * vtktransform, vtkLookupTable *lut, vtkPolyData* original3DObject) { // deprecated settings bool usePointData = false; bool useCellData = false; this->GetDataNode()->GetBoolProperty("deprecated useCellDataForColouring", useCellData); bool scalarVisibility = false; this->GetDataNode()->GetBoolProperty("scalar visibility", scalarVisibility); if(scalarVisibility) { VtkScalarModeProperty* scalarMode; if(this->GetDataNode()->GetProperty(scalarMode, "scalar mode", renderer)) { if( (scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_POINT_DATA) || (scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_DEFAULT) ) { usePointData = true; } if(scalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_CELL_DATA) { useCellData = true; } } else { usePointData = true; } } vtkPoints *vpoints = contour->GetPoints(); vtkDataArray *vpointscalars = contour->GetPointData()->GetScalars(); vtkCellArray *vlines = contour->GetLines(); vtkDataArray* vcellscalars = contour->GetCellData()->GetScalars(); Point3D p; Point2D p2d, last; int i, j; int numberOfLines = vlines->GetNumberOfCells(); glLineWidth( m_LineWidth ); glBegin (GL_LINES); glColor4fv(m_LineColor); double distanceSinceLastNormal(0.0); vlines->InitTraversal(); for(i=0;iGetNextCell(cellSize, cell); vpoints->GetPoint(cell[0], vp); //take transformation via vtktransform into account vtktransform->TransformPoint(vp, vp); vtk2itk(vp, p); //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map(p, p2d); //convert point (until now mm and in world coordinates) to display coordinates (units ) displayGeometry->WorldToDisplay(p2d, p2d); last=p2d; for(j=1; jGetPoint(cell[j], vp); Point3D originalPoint; vtk2itk(vp, originalPoint); //take transformation via vtktransform into account vtktransform->TransformPoint(vp, vp); vtk2itk(vp, p); //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map(p, p2d); //convert point (until now mm and in world coordinates) to display coordinates (units ) displayGeometry->WorldToDisplay(p2d, p2d); vtkFloatingPointType color[3]; if (useCellData && vcellscalars != NULL ) { // color each cell according to cell data lut->GetColor( vcellscalars->GetComponent(i,0),color); glColor3f(color[0],color[1],color[2]); glVertex2f(last[0], last[1]); glVertex2f(p2d[0], p2d[1]); } else if (usePointData && vpointscalars != NULL ) { lut->GetColor( vpointscalars->GetComponent(cell[j-1],0),color); glColor3f(color[0],color[1],color[2]); glVertex2f(last[0], last[1]); lut->GetColor( vpointscalars->GetComponent(cell[j],0),color); glColor3f(color[0],color[1],color[2]); glVertex2f(p2d[0], p2d[1]); } else { glVertex2f(last[0], last[1]); glVertex2f(p2d[0], p2d[1]); // draw normals ? if (m_DrawNormals && original3DObject) { distanceSinceLastNormal += sqrt((p2d[0]-last[0])*(p2d[0]-last[0]) + (p2d[1]-last[1])*(p2d[1]-last[1])); if (distanceSinceLastNormal >= 5.0) { distanceSinceLastNormal = 0.0; vtkPointData* pointData = original3DObject->GetPointData(); if (!pointData) break; vtkDataArray* normalsArray = pointData->GetNormals(); if (!normalsArray) break; // find 3D point closest to the currently drawn point double distance(0.0); vtkIdType closestPointId = m_PointLocator->FindClosestPoint(originalPoint[0], originalPoint[1], originalPoint[2], distance); if (closestPointId >= 0) { // find normal of 3D object at this 3D point double* normal = normalsArray->GetTuple3(closestPointId); double transformedNormal[3]; vtktransform->TransformNormal(normal, transformedNormal); Vector3D normalITK; vtk2itk(transformedNormal, normalITK); normalITK.Normalize(); // calculate a point (point from the cut 3D object) + (normal vector of closest point) Point3D tip3D = p + normalITK; // map this point into our 2D coordinate system Point2D tip2D; worldGeometry->Map(tip3D, tip2D); displayGeometry->WorldToDisplay(tip2D, tip2D); // calculate 2D vector from point to point+normal, normalize it to standard length Vector2D tipVectorGLFront = tip2D - p2d; tipVectorGLFront.Normalize(); tipVectorGLFront *= m_FrontNormalLengthInPixels; Vector2D tipVectorGLBack = p2d - tip2D; tipVectorGLBack.Normalize(); tipVectorGLBack *= m_BackNormalLengthInPixels; Point2D tipPoint2D = p2d + tipVectorGLFront; Point2D backTipPoint2D = p2d + tipVectorGLBack; // draw normalized mapped normal vector glColor4f(m_BackSideColor[0], m_BackSideColor[1], m_BackSideColor[2], m_BackSideColor[3]); // red backside glVertex2f(p2d[0], p2d[1]); glVertex2f(tipPoint2D[0], tipPoint2D[1]); glColor4f(m_FrontSideColor[0], m_FrontSideColor[1], m_FrontSideColor[2], m_FrontSideColor[3]); // green backside glVertex2f(p2d[0], p2d[1]); glVertex2f(backTipPoint2D[0], backTipPoint2D[1]); glColor4fv(m_LineColor); // back to line color } } } } last=p2d; } } glEnd(); glLineWidth(1.0); } void mitk::SurfaceGLMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "line width", IntProperty::New(2), renderer, overwrite ); node->AddProperty( "scalar mode", VtkScalarModeProperty::New(), renderer, overwrite ); node->AddProperty( "draw normals 2D", BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "invert normals", BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "front color", ColorProperty::New(0.0, 1.0, 0.0), renderer, overwrite ); node->AddProperty( "back color", ColorProperty::New(1.0, 0.0, 0.0), renderer, overwrite ); node->AddProperty( "front normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite ); node->AddProperty( "back normal lenth (px)", FloatProperty::New(10.0), renderer, overwrite ); node->AddProperty( "layer", mitk::IntProperty::New(100), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } -void mitk::SurfaceGLMapper2D::ApplyProperties(mitk::BaseRenderer* renderer) +void mitk::SurfaceGLMapper2D::ApplyAllProperties(mitk::BaseRenderer* renderer) { - Superclass::ApplyProperties(renderer); + ApplyColorAndOpacityProperties(renderer); - GetDataNode()->GetBoolProperty("draw normals 2D", m_DrawNormals, renderer); + DataNode * node = GetDataNode(); + + if(node == NULL) + { + return; + } + + node->GetBoolProperty("draw normals 2D", m_DrawNormals, renderer); // check for color and opacity properties, use it for rendering if they exists - GetColor(m_LineColor, renderer /*, "color" */); - GetOpacity(m_LineColor[3], renderer /*, "color" */); + node->GetColor(m_LineColor, renderer, "color"); + node->GetOpacity(m_LineColor[3], renderer, "opacity"); bool invertNormals(false); - if (DataNode* node = GetDataNode()) - { - node->GetBoolProperty("invert normals", invertNormals, renderer); - } + node->GetBoolProperty("invert normals", invertNormals, renderer); if (!invertNormals) { - GetColor(m_FrontSideColor, renderer, "front color"); - GetOpacity(m_FrontSideColor[3], renderer); + node->GetColor(m_FrontSideColor, renderer, "front color"); + node->GetOpacity(m_FrontSideColor[3], renderer, "opacity"); - GetColor(m_BackSideColor, renderer, "back color"); - GetOpacity(m_BackSideColor[3], renderer); + node->GetColor(m_BackSideColor, renderer, "back color"); + node->GetOpacity(m_BackSideColor[3], renderer, "opacity"); + + node->GetFloatProperty( "front normal lenth (px)", m_FrontNormalLengthInPixels, renderer ); + node->GetFloatProperty( "back normal lenth (px)", m_BackNormalLengthInPixels, renderer ); - if (DataNode* node = GetDataNode()) - { - node->GetFloatProperty( "front normal lenth (px)", m_FrontNormalLengthInPixels, renderer ); - node->GetFloatProperty( "back normal lenth (px)", m_BackNormalLengthInPixels, renderer ); - } } else { - GetColor(m_FrontSideColor, renderer, "back color"); - GetOpacity(m_FrontSideColor[3], renderer); + node->GetColor(m_FrontSideColor, renderer, "back color"); + node->GetOpacity(m_FrontSideColor[3], renderer, "opacity"); - GetColor(m_BackSideColor, renderer, "front color"); - GetOpacity(m_BackSideColor[3], renderer); + node->GetColor(m_BackSideColor, renderer, "front color"); + node->GetOpacity(m_BackSideColor[3], renderer, "opacity"); + + node->GetFloatProperty( "back normal lenth (px)", m_FrontNormalLengthInPixels, renderer ); + node->GetFloatProperty( "front normal lenth (px)", m_BackNormalLengthInPixels, renderer ); - if (DataNode* node = GetDataNode()) - { - node->GetFloatProperty( "back normal lenth (px)", m_FrontNormalLengthInPixels, renderer ); - node->GetFloatProperty( "front normal lenth (px)", m_BackNormalLengthInPixels, renderer ); - } } } diff --git a/Core/Code/Rendering/mitkSurfaceGLMapper2D.h b/Core/Code/Rendering/mitkSurfaceGLMapper2D.h index bab8373dfb..04630969d1 100644 --- a/Core/Code/Rendering/mitkSurfaceGLMapper2D.h +++ b/Core/Code/Rendering/mitkSurfaceGLMapper2D.h @@ -1,155 +1,155 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKSURFACEDATAMAPPER2D_H_HEADER_INCLUDED_C10EB2E8 #define MITKSURFACEDATAMAPPER2D_H_HEADER_INCLUDED_C10EB2E8 #include -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" #include "mitkSurface.h" class vtkCutter; class vtkPlane; class vtkLookupTable; class vtkLinearTransform; class vtkPKdTree; class vtkStripper; namespace mitk { class BaseRenderer; class Geometry2D; class DisplayGeometry; /** * @brief OpenGL-based mapper to display a Surface in a 2D window. * * Displays a 2D cut through a Surface object (vtkPolyData). This * is basically done in two steps: * * 1. Cut a slice out of a (input) vtkPolyData object. The slice may be a flat plane (PlaneGeometry) * or a curved plane (ThinPlateSplineCurvedGeometry). The actual cutting is done by a vtkCutter. * The result of cutting is a (3D) vtkPolyData object, which contains only points and lines * describing the cut. * * 2. Paint the cut out slice by means of OpenGL. To do this, all lines of the cut object are traversed. * For each line segment, both end points are transformed from 3D into the 2D system of the associated * renderer and then drawn by OpenGL. * * There is a mode to display normals of the input surface object (see properties below). If this mode * is on, then the drawing of the 2D cut is slightly more complicated. For each line segment of the cut, * we take the end point (p2d) of this line and search the input vtkPolyData object for the closest point to p2d (p3D-input). * We then read out the surface normal for p3D-input. We map this normal into our 2D coordinate system and * then draw a line from p2d to (p2d+mapped normal). This drawing of surface normals will only work if the * input vtkPolyData actually HAS normals. If you have a vtkPolyData without normals, use the vtkPolyDataNormals * filter to generate normals. * * Properties that influence rendering are: * * - \b "color": (ColorProperty) Color of surface object * - \b "line width": (IntProperty) Width in pixels of the lines drawn. * - \b "scalar visibility": (BoolProperty) Whether point/cell data values (from vtkPolyData) should be used to influence colors * - \b "scalar mode": (BoolProperty) If "scalar visibility" is on, whether to use point data or cell data for coloring. * - \b "LookupTable": (LookupTableProperty) A lookup table to translate point/cell data values (from vtkPolyData) to colors * - \b "ScalarsRangeMinimum": (FloatProperty) Range of the lookup table * - \b "ScalarsRangeMaximum": (FloatProperty) Range of the lookup table * - \b "draw normals 2D": (BoolProperty) If true, normals are drawn (if present in vtkPolyData) * - \b "invert normals": (BoolProperty) Inverts front/back for display. * - \b "front color": (ColorProperty) Color for normals display on front side of the plane * - \b "front normal length (px)": (FloatProperty) Length of the front side normals in pixels. * - \b "back color": (ColorProperty) Color for normals display on back side of the plane * - \b "back normal length (px)": (FloatProperty) Length of the back side normals in pixels. * */ -class MITK_CORE_EXPORT SurfaceGLMapper2D : public GLMapper2D +class MITK_CORE_EXPORT SurfaceGLMapper2D : public GLMapper { public: - mitkClassMacro(SurfaceGLMapper2D, GLMapper2D); + mitkClassMacro(SurfaceGLMapper2D, GLMapper); itkNewMacro(Self); const Surface* GetInput(void); virtual void Paint(BaseRenderer* renderer); /** * @brief The Surface to map can be explicitly set by this method. * * If it is set, it is used instead of the data stored in the DataNode. * This enables to use the mapper also internally from other mappers. */ itkSetConstObjectMacro(Surface, Surface); /** * @brief Get the Surface set explicitly. * * @return NULL is returned if no Surface is set to be used instead of DataNode::GetData(). * @sa SetSurface */ itkGetConstObjectMacro(Surface, Surface); /** *\brief Overwritten to initialize lookup table for point scalar data */ void SetDataNode( DataNode* node ); /** * \brief Generate OpenGL primitives for the VTK contour held in contour. */ void PaintCells(BaseRenderer* renderer, vtkPolyData* contour, const Geometry2D* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform* vtktransform, vtkLookupTable* lut = NULL, vtkPolyData* original3DObject = NULL); static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false); - virtual void ApplyProperties(BaseRenderer* renderer); + virtual void ApplyAllProperties(BaseRenderer* renderer); protected: SurfaceGLMapper2D(); virtual ~SurfaceGLMapper2D(); vtkPlane* m_Plane; vtkCutter* m_Cutter; Surface::ConstPointer m_Surface; vtkLookupTable* m_LUT; int m_LineWidth; vtkPKdTree* m_PointLocator; vtkStripper* m_Stripper; bool m_DrawNormals; float m_FrontSideColor[4]; float m_BackSideColor[4]; float m_LineColor[4]; float m_FrontNormalLengthInPixels; float m_BackNormalLengthInPixels; }; } // namespace mitk #endif /* MITKSURFACEDATAMAPPER2D_H_HEADER_INCLUDED_C10EB2E8 */ diff --git a/Core/Code/Rendering/mitkSurfaceVtkMapper3D.cpp b/Core/Code/Rendering/mitkSurfaceVtkMapper3D.cpp index 5eb7fb4246..8157babcf9 100644 --- a/Core/Code/Rendering/mitkSurfaceVtkMapper3D.cpp +++ b/Core/Code/Rendering/mitkSurfaceVtkMapper3D.cpp @@ -1,503 +1,504 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSurfaceVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkColorProperty.h" #include "mitkLookupTableProperty.h" #include "mitkVtkRepresentationProperty.h" #include "mitkVtkInterpolationProperty.h" #include "mitkVtkScalarModeProperty.h" #include "mitkClippingProperty.h" #include "mitkSmartPointerProperty.h" #include "mitkShaderProperty.h" #include "mitkShaderRepository.h" #include #include //VTK #include #include #include #include #include #include #include #include const mitk::Surface* mitk::SurfaceVtkMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } mitk::SurfaceVtkMapper3D::SurfaceVtkMapper3D() { // m_Prop3D = vtkActor::New(); m_GenerateNormals = false; } mitk::SurfaceVtkMapper3D::~SurfaceVtkMapper3D() { // m_Prop3D->Delete(); } void mitk::SurfaceVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - bool visible = IsVisible(renderer); + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); - if(visible==false) - { - ls->m_Actor->VisibilityOff(); - return; - } - - // - // set the input-object at time t for the mapper - // - mitk::Surface::Pointer input = const_cast< mitk::Surface* >( this->GetInput() ); - vtkPolyData * polydata = input->GetVtkPolyData( this->GetTimestep() ); - if(polydata == NULL) - { - ls->m_Actor->VisibilityOff(); - return; - } - - if ( m_GenerateNormals ) - { - ls->m_VtkPolyDataNormals->SetInput( polydata ); - ls->m_VtkPolyDataMapper->SetInput( ls->m_VtkPolyDataNormals->GetOutput() ); - } - else - { - ls->m_VtkPolyDataMapper->SetInput( polydata ); - } - - // - // apply properties read from the PropertyList - // - ApplyProperties(ls->m_Actor, renderer); - - if(visible) - ls->m_Actor->VisibilityOn(); + if(!visible) + { + ls->m_Actor->VisibilityOff(); + return; + } + + // + // set the input-object at time t for the mapper + // + mitk::Surface::Pointer input = const_cast< mitk::Surface* >( this->GetInput() ); + vtkPolyData * polydata = input->GetVtkPolyData( this->GetTimestep() ); + if(polydata == NULL) + { + ls->m_Actor->VisibilityOff(); + return; + } + + if ( m_GenerateNormals ) + { + ls->m_VtkPolyDataNormals->SetInput( polydata ); + ls->m_VtkPolyDataMapper->SetInput( ls->m_VtkPolyDataNormals->GetOutput() ); + } + else + { + ls->m_VtkPolyDataMapper->SetInput( polydata ); + } + + // + // apply properties read from the PropertyList + // + ApplyAllProperties(renderer, ls->m_Actor); + + if(visible) + ls->m_Actor->VisibilityOn(); } void mitk::SurfaceVtkMapper3D::ResetMapper( BaseRenderer* renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); ls->m_Actor->VisibilityOff(); } void mitk::SurfaceVtkMapper3D::ApplyMitkPropertiesToVtkProperty(mitk::DataNode *node, vtkProperty* property, mitk::BaseRenderer* renderer) { // Backface culling { mitk::BoolProperty::Pointer p; node->GetProperty(p, "Backface Culling", renderer); bool useCulling = false; if(p.IsNotNull()) useCulling = p->GetValue(); property->SetBackfaceCulling(useCulling); } // Colors { double ambient [3] = { 0.5,0.5,0.0 }; double diffuse [3] = { 0.5,0.5,0.0 }; double specular[3] = { 1.0,1.0,1.0 }; float coeff_ambient = 0.5f; float coeff_diffuse = 0.5f; float coeff_specular= 0.5f; float power_specular=10.0f; // Color { mitk::ColorProperty::Pointer p; node->GetProperty(p, "color", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); ambient[0]=c.GetRed(); ambient[1]=c.GetGreen(); ambient[2]=c.GetBlue(); diffuse[0]=c.GetRed(); diffuse[1]=c.GetGreen(); diffuse[2]=c.GetBlue(); // Setting specular color to the same, make physically no real sense, however vtk rendering slows down, if these colors are different. specular[0]=c.GetRed(); specular[1]=c.GetGreen(); specular[2]=c.GetBlue(); } } // Ambient { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.ambientColor", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); ambient[0]=c.GetRed(); ambient[1]=c.GetGreen(); ambient[2]=c.GetBlue(); } } // Diffuse { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.diffuseColor", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); diffuse[0]=c.GetRed(); diffuse[1]=c.GetGreen(); diffuse[2]=c.GetBlue(); } } // Specular { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.specularColor", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); specular[0]=c.GetRed(); specular[1]=c.GetGreen(); specular[2]=c.GetBlue(); } } // Ambient coeff { node->GetFloatProperty("material.ambientCoefficient", coeff_ambient, renderer); } // Diffuse coeff { node->GetFloatProperty("material.diffuseCoefficient", coeff_diffuse, renderer); } // Specular coeff { node->GetFloatProperty("material.specularCoefficient", coeff_specular, renderer); } // Specular power { node->GetFloatProperty("material.specularPower", power_specular, renderer); } property->SetAmbient( coeff_ambient ); property->SetDiffuse( coeff_diffuse ); property->SetSpecular( coeff_specular ); property->SetSpecularPower( power_specular ); property->SetAmbientColor( ambient ); property->SetDiffuseColor( diffuse ); property->SetSpecularColor( specular ); } // Render mode { // Opacity { float opacity = 1.0f; if( node->GetOpacity(opacity,renderer) ) property->SetOpacity( opacity ); } // Wireframe line width { float lineWidth = 1; node->GetFloatProperty("material.wireframeLineWidth", lineWidth, renderer); property->SetLineWidth( lineWidth ); } // Representation { mitk::VtkRepresentationProperty::Pointer p; node->GetProperty(p, "material.representation", renderer); if(p.IsNotNull()) property->SetRepresentation( p->GetVtkRepresentation() ); } // Interpolation { mitk::VtkInterpolationProperty::Pointer p; node->GetProperty(p, "material.interpolation", renderer); if(p.IsNotNull()) property->SetInterpolation( p->GetVtkInterpolation() ); } } } -void mitk::SurfaceVtkMapper3D::ApplyProperties(vtkActor* /*actor*/, mitk::BaseRenderer* renderer) +void mitk::SurfaceVtkMapper3D::ApplyAllProperties( mitk::BaseRenderer* renderer, vtkActor* /*actor*/) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // Applying shading properties { - Superclass::ApplyProperties( ls->m_Actor, renderer ) ; + Superclass::ApplyColorAndOpacityProperties( renderer, ls->m_Actor ) ; // VTK Properties ApplyMitkPropertiesToVtkProperty( this->GetDataNode(), ls->m_Actor->GetProperty(), renderer ); // Shaders mitk::ShaderRepository::GetGlobalShaderRepository()->ApplyProperties(this->GetDataNode(),ls->m_Actor,renderer,ls->m_ShaderTimestampUpdate); } mitk::LookupTableProperty::Pointer lookupTableProp; this->GetDataNode()->GetProperty(lookupTableProp, "LookupTable", renderer); if (lookupTableProp.IsNotNull() ) { ls->m_VtkPolyDataMapper->SetLookupTable(lookupTableProp->GetLookupTable()->GetVtkLookupTable()); } mitk::LevelWindow levelWindow; if(this->GetDataNode()->GetLevelWindow(levelWindow, renderer, "levelWindow")) { ls->m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetLowerWindowBound(),levelWindow.GetUpperWindowBound()); } else if(this->GetDataNode()->GetLevelWindow(levelWindow, renderer)) { ls->m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetLowerWindowBound(),levelWindow.GetUpperWindowBound()); } bool scalarVisibility = false; this->GetDataNode()->GetBoolProperty("scalar visibility", scalarVisibility); ls->m_VtkPolyDataMapper->SetScalarVisibility( (scalarVisibility ? 1 : 0) ); if(scalarVisibility) { mitk::VtkScalarModeProperty* scalarMode; if(this->GetDataNode()->GetProperty(scalarMode, "scalar mode", renderer)) { ls->m_VtkPolyDataMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); } else ls->m_VtkPolyDataMapper->SetScalarModeToDefault(); bool colorMode = false; this->GetDataNode()->GetBoolProperty("color mode", colorMode); ls->m_VtkPolyDataMapper->SetColorMode( (colorMode ? 1 : 0) ); float scalarsMin = 0; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum")) != NULL) scalarsMin = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum"))->GetValue(); float scalarsMax = 1.0; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum")) != NULL) scalarsMax = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum"))->GetValue(); ls->m_VtkPolyDataMapper->SetScalarRange(scalarsMin,scalarsMax); } mitk::SmartPointerProperty::Pointer imagetextureProp; imagetextureProp = dynamic_cast< mitk::SmartPointerProperty * >( GetDataNode()->GetProperty("Surface.Texture", renderer)); if(imagetextureProp.IsNotNull()) { mitk::Image* miktTexture = dynamic_cast< mitk::Image* >( imagetextureProp->GetSmartPointer().GetPointer() ); vtkSmartPointer vtkTxture = vtkSmartPointer::New(); //Either select the first slice of a volume if(miktTexture->GetDimension(2) > 1) { MITK_WARN << "3D Textures are not supported by VTK and MITK. The first slice of the volume will be used instead!"; mitk::ImageSliceSelector::Pointer sliceselector = mitk::ImageSliceSelector::New(); sliceselector->SetSliceNr(0); sliceselector->SetChannelNr(0); sliceselector->SetTimeNr(0); sliceselector->SetInput(miktTexture); sliceselector->Update(); vtkTxture->SetInput(sliceselector->GetOutput()->GetVtkImageData()); } else //or just use the 2D image { vtkTxture->SetInput(miktTexture->GetVtkImageData()); } //pass the texture to the actor ls->m_Actor->SetTexture(vtkTxture); if(ls->m_VtkPolyDataMapper->GetInput()->GetPointData()->GetTCoords() == NULL) { MITK_ERROR << "Surface.Texture property was set, but there are no texture coordinates. Please provide texture coordinates for the vtkPolyData via vtkPolyData->GetPointData()->SetTCoords()."; } } // deprecated settings bool deprecatedUseCellData = false; this->GetDataNode()->GetBoolProperty("deprecated useCellDataForColouring", deprecatedUseCellData); bool deprecatedUsePointData = false; this->GetDataNode()->GetBoolProperty("deprecated usePointDataForColouring", deprecatedUsePointData); if (deprecatedUseCellData) { ls->m_VtkPolyDataMapper->SetColorModeToDefault(); ls->m_VtkPolyDataMapper->SetScalarRange(0,255); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_VtkPolyDataMapper->SetScalarModeToUseCellData(); ls->m_Actor->GetProperty()->SetSpecular (1); ls->m_Actor->GetProperty()->SetSpecularPower (50); ls->m_Actor->GetProperty()->SetInterpolationToPhong(); } else if (deprecatedUsePointData) { float scalarsMin = 0; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum")) != NULL) scalarsMin = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum"))->GetValue(); float scalarsMax = 0.1; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum")) != NULL) scalarsMax = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum"))->GetValue(); ls->m_VtkPolyDataMapper->SetScalarRange(scalarsMin,scalarsMax); ls->m_VtkPolyDataMapper->SetColorModeToMapScalars(); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_Actor->GetProperty()->SetSpecular (1); ls->m_Actor->GetProperty()->SetSpecularPower (50); ls->m_Actor->GetProperty()->SetInterpolationToPhong(); } int deprecatedScalarMode = VTK_COLOR_MODE_DEFAULT; if(this->GetDataNode()->GetIntProperty("deprecated scalar mode", deprecatedScalarMode, renderer)) { ls->m_VtkPolyDataMapper->SetScalarMode(deprecatedScalarMode); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_Actor->GetProperty()->SetSpecular (1); ls->m_Actor->GetProperty()->SetSpecularPower (50); //m_Actor->GetProperty()->SetInterpolationToPhong(); } // Check whether one or more ClippingProperty objects have been defined for // this node. Check both renderer specific and global property lists, since // properties in both should be considered. const PropertyList::PropertyMap *rendererProperties = this->GetDataNode()->GetPropertyList( renderer )->GetMap(); const PropertyList::PropertyMap *globalProperties = this->GetDataNode()->GetPropertyList( NULL )->GetMap(); // Add clipping planes (if any) ls->m_ClippingPlaneCollection->RemoveAllItems(); PropertyList::PropertyMap::const_iterator it; for ( it = rendererProperties->begin(); it != rendererProperties->end(); ++it ) { this->CheckForClippingProperty( renderer,(*it).second.GetPointer() ); } for ( it = globalProperties->begin(); it != globalProperties->end(); ++it ) { this->CheckForClippingProperty( renderer,(*it).second.GetPointer() ); } if ( ls->m_ClippingPlaneCollection->GetNumberOfItems() > 0 ) { ls->m_VtkPolyDataMapper->SetClippingPlanes( ls->m_ClippingPlaneCollection ); } else { ls->m_VtkPolyDataMapper->RemoveAllClippingPlanes(); } } vtkProp *mitk::SurfaceVtkMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); return ls->m_Actor; } void mitk::SurfaceVtkMapper3D::CheckForClippingProperty( mitk::BaseRenderer* renderer, mitk::BaseProperty *property ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // m_Prop3D = ls->m_Actor; ClippingProperty *clippingProperty = dynamic_cast< ClippingProperty * >( property ); if ( (clippingProperty != NULL) && (clippingProperty->GetClippingEnabled()) ) { const Point3D &origin = clippingProperty->GetOrigin(); const Vector3D &normal = clippingProperty->GetNormal(); vtkPlane *clippingPlane = vtkPlane::New(); clippingPlane->SetOrigin( origin[0], origin[1], origin[2] ); clippingPlane->SetNormal( normal[0], normal[1], normal[2] ); ls->m_ClippingPlaneCollection->AddItem( clippingPlane ); clippingPlane->UnRegister( NULL ); } } void mitk::SurfaceVtkMapper3D::SetDefaultPropertiesForVtkProperty(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { // Shading { node->AddProperty( "material.wireframeLineWidth", mitk::FloatProperty::New(1.0f) , renderer, overwrite ); node->AddProperty( "material.ambientCoefficient" , mitk::FloatProperty::New(0.05f) , renderer, overwrite ); node->AddProperty( "material.diffuseCoefficient" , mitk::FloatProperty::New(0.9f) , renderer, overwrite ); node->AddProperty( "material.specularCoefficient", mitk::FloatProperty::New(1.0f) , renderer, overwrite ); node->AddProperty( "material.specularPower" , mitk::FloatProperty::New(16.0f) , renderer, overwrite ); //node->AddProperty( "material.ambientColor" , mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); //node->AddProperty( "material.diffuseColor" , mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); //node->AddProperty( "material.specularColor" , mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); node->AddProperty( "material.representation" , mitk::VtkRepresentationProperty::New() , renderer, overwrite ); node->AddProperty( "material.interpolation" , mitk::VtkInterpolationProperty::New() , renderer, overwrite ); } // Shaders { mitk::ShaderRepository::GetGlobalShaderRepository()->AddDefaultProperties(node,renderer,overwrite); } } void mitk::SurfaceVtkMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "color", mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); node->AddProperty( "opacity", mitk::FloatProperty::New(1.0), renderer, overwrite ); mitk::SurfaceVtkMapper3D::SetDefaultPropertiesForVtkProperty(node,renderer,overwrite); // Shading node->AddProperty( "scalar visibility", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "color mode", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "scalar mode", mitk::VtkScalarModeProperty::New(), renderer, overwrite ); mitk::Surface::Pointer surface = dynamic_cast(node->GetData()); if(surface.IsNotNull()) { if((surface->GetVtkPolyData() != 0) && (surface->GetVtkPolyData()->GetPointData() != NULL) && (surface->GetVtkPolyData()->GetPointData()->GetScalars() != 0)) { node->AddProperty( "scalar visibility", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "color mode", mitk::BoolProperty::New(true), renderer, overwrite ); } } // Backface culling node->AddProperty( "Backface Culling", mitk::BoolProperty::New(false), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } void mitk::SurfaceVtkMapper3D::SetImmediateModeRenderingOn(int /*on*/) { /* if (m_VtkPolyDataMapper != NULL) m_VtkPolyDataMapper->SetImmediateModeRendering(on); */ } diff --git a/Core/Code/Rendering/mitkSurfaceVtkMapper3D.h b/Core/Code/Rendering/mitkSurfaceVtkMapper3D.h index 2e55f800e5..b460eae2f8 100644 --- a/Core/Code/Rendering/mitkSurfaceVtkMapper3D.h +++ b/Core/Code/Rendering/mitkSurfaceVtkMapper3D.h @@ -1,162 +1,162 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKSURFACEDATAVTKMAPPER3D_H_HEADER_INCLUDED_C1907273 #define MITKSURFACEDATAVTKMAPPER3D_H_HEADER_INCLUDED_C1907273 #include -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include "mitkSurface.h" #include "mitkBaseRenderer.h" #include #include #include #include #include #include namespace mitk { //##Documentation //## @brief Vtk-based mapper for Surface //## //## @ingroup Mapper /** * @brief Vtk-based mapper for Surface * * Properties that can be set for surfaces and influence the surfaceVTKMapper3D are: * * - \b "Backface Culling": True enables backface culling, which means only front-facing polygons will be visualized. False/disabled by default. * - \b "color": (ColorProperty) Diffuse color of the surface object (this property will be read when material.diffuseColor is not defined) * - \b "Opacity": (FloatProperty) Opacity of the surface object * - \b "material.ambientColor": (ColorProperty) Ambient color of the surface object * - \b "material.ambientCoefficient": ( FloatProperty) Ambient coefficient of the surface object * - \b "material.diffuseColor": ( ColorProperty) Diffuse color of the surface object * - \b "material.diffuseCoefficient": (FloatProperty) Diffuse coefficient of the surface object * - \b "material.specularColor": (ColorProperty) Specular Color of the surface object * - \b "material.specularCoefficient": (FloatProperty) Specular coefficient of the surface object * - \b "material.specularPower": (FloatProperty) Specular power of the surface object * - \b "material.interpolation": (VtkInterpolationProperty) Interpolation * - \b "material.representation": (VtkRepresentationProperty*) Representation * - \b "material.wireframeLineWidth": (FloatProperty) Width in pixels of the lines drawn. * - \b "scalar visibility": (BoolProperty) If the scarlars of the surface are visible * Properties to look for are: * * - \b "scalar visibility": if set to on, scalars assigned to the data are shown * Turn this on if using a lookup table. * - \b "ScalarsRangeMinimum": Optional. Can be used to store the scalar min, e.g. * for the level window settings. * - \b "ScalarsRangeMaximum": Optional. See above. * * There might be still some other, deprecated properties. These will not be documented anymore. * Please check the source if you really need them. * * @ingroup Mapper */ -class MITK_CORE_EXPORT SurfaceVtkMapper3D : public VtkMapper3D +class MITK_CORE_EXPORT SurfaceVtkMapper3D : public VtkMapper { public: - mitkClassMacro(SurfaceVtkMapper3D, VtkMapper3D); + mitkClassMacro(SurfaceVtkMapper3D, VtkMapper); itkNewMacro(Self); itkSetMacro(GenerateNormals, bool); itkGetMacro(GenerateNormals, bool); //enable ImmediateModeRendering for vtkMapping //yet to solve bug 1398 void SetImmediateModeRenderingOn(int on = 1); itkGetMacro(ImmediateModeRenderingOn, int); virtual const mitk::Surface* GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); - virtual void ApplyProperties(vtkActor* actor, mitk::BaseRenderer* renderer); + virtual void ApplyAllProperties(mitk::BaseRenderer* renderer, vtkActor* actor); static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); protected: SurfaceVtkMapper3D(); virtual ~SurfaceVtkMapper3D(); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); virtual void ResetMapper( mitk::BaseRenderer* renderer ); /** Checks whether the specified property is a ClippingProperty and if yes, * adds it to m_ClippingPlaneCollection (internal method). */ virtual void CheckForClippingProperty( mitk::BaseRenderer* renderer, mitk::BaseProperty *property ); bool m_GenerateNormals; //enable ImmediateModeRendering for the vtkMapper int m_ImmediateModeRenderingOn; public: class LocalStorage : public mitk::Mapper::BaseLocalStorage { public: vtkActor* m_Actor; vtkPolyDataMapper *m_VtkPolyDataMapper; vtkPolyDataNormals *m_VtkPolyDataNormals; vtkPlaneCollection *m_ClippingPlaneCollection; itk::TimeStamp m_ShaderTimestampUpdate; LocalStorage() { m_VtkPolyDataMapper = vtkOpenGLPolyDataMapper::New(); m_VtkPolyDataNormals = vtkPolyDataNormals::New(); m_Actor = vtkActor::New(); m_ClippingPlaneCollection = vtkPlaneCollection::New(); m_Actor->SetMapper(m_VtkPolyDataMapper); } ~LocalStorage() { m_VtkPolyDataMapper->Delete(); m_VtkPolyDataNormals->Delete(); m_Actor->Delete(); m_ClippingPlaneCollection->Delete(); } }; mitk::Mapper::LocalStorageHandler m_LSH; static void ApplyMitkPropertiesToVtkProperty(mitk::DataNode *node, vtkProperty* property, mitk::BaseRenderer* renderer); static void SetDefaultPropertiesForVtkProperty(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite); }; } // namespace mitk #endif /* MITKSURFACEDATAVTKMAPPER3D_H_HEADER_INCLUDED_C1907273 */ diff --git a/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.cpp b/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.cpp index b21d338bf5..a99ea97659 100644 --- a/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.cpp +++ b/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.cpp @@ -1,707 +1,707 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkVolumeDataVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkLevelWindow.h" #include "mitkColorProperty.h" #include "mitkLevelWindowProperty.h" #include "mitkLookupTableProperty.h" #include "mitkTransferFunctionProperty.h" #include "mitkTransferFunctionInitializer.h" #include "mitkColorProperty.h" #include "mitkVtkPropRenderer.h" #include "mitkRenderingManager.h" #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 "mitkVtkVolumeRenderingProperty.h" #include const mitk::Image* mitk::VolumeDataVtkMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } mitk::VolumeDataVtkMapper3D::VolumeDataVtkMapper3D() : m_Mask( NULL ) { m_PlaneSet = false; m_ClippingPlane = vtkPlane::New(); m_PlaneWidget = vtkImplicitPlaneWidget::New(); /* m_T2DMapper = vtkVolumeTextureMapper2D::New(); m_T2DMapper->SetMaximumNumberOfPlanes( 100 ); */ m_HiResMapper = vtkVolumeRayCastMapper::New(); m_HiResMapper->SetSampleDistance(1.0); // 4 rays for every pixel m_HiResMapper->IntermixIntersectingGeometryOn(); m_HiResMapper->SetNumberOfThreads( itk::MultiThreader::GetGlobalDefaultNumberOfThreads() ); /* vtkVolumeRayCastCompositeFunction* compositeFunction = vtkVolumeRayCastCompositeFunction::New(); compositeFunction->SetCompositeMethodToClassifyFirst(); m_HiResMapper->SetVolumeRayCastFunction(compositeFunction); compositeFunction->Delete(); vtkVolumeRayCastMIPFunction* mipFunction = vtkVolumeRayCastMIPFunction::New(); m_HiResMapper->SetVolumeRayCastFunction(mipFunction); mipFunction->Delete(); */ vtkFiniteDifferenceGradientEstimator* gradientEstimator = vtkFiniteDifferenceGradientEstimator::New(); m_HiResMapper->SetGradientEstimator(gradientEstimator); gradientEstimator->Delete(); m_VolumePropertyLow = vtkVolumeProperty::New(); m_VolumePropertyMed = vtkVolumeProperty::New(); m_VolumePropertyHigh = vtkVolumeProperty::New(); m_VolumeLOD = vtkLODProp3D::New(); m_VolumeLOD->VisibilityOff(); m_HiResID = m_VolumeLOD->AddLOD(m_HiResMapper,m_VolumePropertyHigh,0.0); // RayCast // m_LowResID = m_VolumeLOD->AddLOD(m_T2DMapper,m_VolumePropertyLow,0.0); // TextureMapper2D m_MedResID = m_VolumeLOD->AddLOD(m_HiResMapper,m_VolumePropertyMed,0.0); // RayCast m_Resampler = vtkImageResample::New(); m_Resampler->SetAxisMagnificationFactor(0,0.25); m_Resampler->SetAxisMagnificationFactor(1,0.25); m_Resampler->SetAxisMagnificationFactor(2,0.25); // For abort rendering mechanism m_VolumeLOD->AutomaticLODSelectionOff(); m_BoundingBox = vtkCubeSource::New(); m_BoundingBox->SetXLength( 0.0 ); m_BoundingBox->SetYLength( 0.0 ); m_BoundingBox->SetZLength( 0.0 ); m_BoundingBoxMapper = vtkPolyDataMapper::New(); m_BoundingBoxMapper->SetInput( m_BoundingBox->GetOutput() ); m_BoundingBoxActor = vtkActor::New(); m_BoundingBoxActor->SetMapper( m_BoundingBoxMapper ); m_BoundingBoxActor->GetProperty()->SetColor( 1.0, 1.0, 1.0 ); m_BoundingBoxActor->GetProperty()->SetRepresentationToWireframe(); // BoundingBox rendering is not working due to problem with assembly // transformation; see bug #454 // If commenting in the following, do not forget to comment in the // m_Prop3DAssembly->Delete() line in the destructor. //m_Prop3DAssembly = vtkAssembly::New(); //m_Prop3DAssembly->AddPart( m_VolumeLOD ); //m_Prop3DAssembly->AddPart( m_BoundingBoxActor ); //m_Prop3D = m_Prop3DAssembly; m_ImageCast = vtkImageShiftScale::New(); m_ImageCast->SetOutputScalarTypeToUnsignedShort(); m_ImageCast->ClampOverflowOn(); m_UnitSpacingImageFilter = vtkImageChangeInformation::New(); m_UnitSpacingImageFilter->SetInput(m_ImageCast->GetOutput()); m_UnitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 ); m_ImageMaskFilter = vtkImageMask::New(); m_ImageMaskFilter->SetMaskedOutputValue(0xffff); this->m_Resampler->SetInput( this->m_UnitSpacingImageFilter->GetOutput() ); this->m_HiResMapper->SetInput( this->m_UnitSpacingImageFilter->GetOutput() ); // m_T2DMapper->SetInput(m_Resampler->GetOutput()); this->CreateDefaultTransferFunctions(); } vtkProp *mitk::VolumeDataVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) { return m_VolumeLOD; } mitk::VolumeDataVtkMapper3D::~VolumeDataVtkMapper3D() { m_UnitSpacingImageFilter->Delete(); m_ImageCast->Delete(); // m_T2DMapper->Delete(); m_HiResMapper->Delete(); m_Resampler->Delete(); m_VolumePropertyLow->Delete(); m_VolumePropertyMed->Delete(); m_VolumePropertyHigh->Delete(); m_VolumeLOD->Delete(); m_ClippingPlane->Delete(); m_PlaneWidget->Delete(); // m_Prop3DAssembly->Delete(); m_BoundingBox->Delete(); m_BoundingBoxMapper->Delete(); m_BoundingBoxActor->Delete(); m_ImageMaskFilter->Delete(); m_DefaultColorTransferFunction->Delete(); m_DefaultOpacityTransferFunction->Delete(); m_DefaultGradientTransferFunction->Delete(); if (m_Mask) { m_Mask->Delete(); } } void mitk::VolumeDataVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { SetVtkMapperImmediateModeRendering(m_BoundingBoxMapper); mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); if ( !input || !input->IsInitialized() ) return; vtkRenderWindow* renderWindow = renderer->GetRenderWindow(); bool volumeRenderingEnabled = true; - if (this->IsVisible(renderer)==false || + bool visible = true; + + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible || this->GetDataNode() == NULL || dynamic_cast(GetDataNode()->GetProperty("volumerendering",renderer))==NULL || dynamic_cast(GetDataNode()->GetProperty("volumerendering",renderer))->GetValue() == false ) { volumeRenderingEnabled = false; // Check if a bounding box should be displayed around the dataset // (even if volume rendering is disabled) bool hasBoundingBox = false; this->GetDataNode()->GetBoolProperty( "bounding box", hasBoundingBox ); if ( !hasBoundingBox ) { m_BoundingBoxActor->VisibilityOff(); } else { m_BoundingBoxActor->VisibilityOn(); const BoundingBox::BoundsArrayType &bounds = input->GetTimeSlicedGeometry()->GetBounds(); m_BoundingBox->SetBounds( bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5] ); ColorProperty *colorProperty; if ( this->GetDataNode()->GetProperty( colorProperty, "color" ) ) { const mitk::Color &color = colorProperty->GetColor(); m_BoundingBoxActor->GetProperty()->SetColor( color[0], color[1], color[2] ); } else { m_BoundingBoxActor->GetProperty()->SetColor( 1.0, 1.0, 1.0 ); } } } // Don't do anything if VR is disabled if ( !volumeRenderingEnabled ) { m_VolumeLOD->VisibilityOff(); return; } else { mitk::VtkVolumeRenderingProperty* vrp=dynamic_cast(GetDataNode()->GetProperty("volumerendering configuration",renderer)); if(vrp) { int renderingValue = vrp->GetValueAsId(); switch(renderingValue) { case VTK_VOLUME_RAY_CAST_MIP_FUNCTION: { vtkVolumeRayCastMIPFunction* mipFunction = vtkVolumeRayCastMIPFunction::New(); m_HiResMapper->SetVolumeRayCastFunction(mipFunction); mipFunction->Delete(); MITK_INFO <<"in switch" <SetCompositeMethodToClassifyFirst(); m_HiResMapper->SetVolumeRayCastFunction(compositeFunction); compositeFunction->Delete(); break; } default: MITK_ERROR <<"Warning: invalid volume rendering option. " << std::endl; } } m_VolumeLOD->VisibilityOn(); } this->SetPreferences(); /* switch ( mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ) ) { case 0: m_VolumeLOD->SetSelectedLODID(m_MedResID); m_LowResID ); break; default: case 1: m_VolumeLOD->SetSelectedLODID( m_HiResID ); break; } */ m_VolumeLOD->SetSelectedLODID( m_HiResID ); assert(input->GetTimeSlicedGeometry()); const Geometry3D* worldgeometry = renderer->GetCurrentWorldGeometry(); if(worldgeometry==NULL) { GetDataNode()->SetProperty("volumerendering",mitk::BoolProperty::New(false)); return; } vtkImageData *inputData = input->GetVtkImageData( this->GetTimestep() ); if(inputData==NULL) return; m_ImageCast->SetInput( inputData ); //If mask exists, process mask before resampling. if (this->m_Mask) { this->m_ImageMaskFilter->SetImageInput(this->m_UnitSpacingImageFilter->GetOutput()); this->m_Resampler->SetInput(this->m_ImageMaskFilter->GetOutput()); this->m_HiResMapper->SetInput(this->m_ImageMaskFilter->GetOutput()); } else { this->m_Resampler->SetInput(this->m_UnitSpacingImageFilter->GetOutput()); this->m_HiResMapper->SetInput(this->m_UnitSpacingImageFilter->GetOutput()); } this->UpdateTransferFunctions( renderer ); vtkRenderWindowInteractor *interactor = renderWindow->GetInteractor(); float frameRate; if( this->GetDataNode()->GetFloatProperty( "framerate", frameRate ) && frameRate > 0 && frameRate <= 60) { interactor->SetDesiredUpdateRate( frameRate ); interactor->SetStillUpdateRate( frameRate ); } else if( frameRate > 60 ) { this->GetDataNode()->SetProperty( "framerate",mitk::FloatProperty::New(60)); interactor->SetDesiredUpdateRate( 60 ); interactor->SetStillUpdateRate( 60 ); } else { this->GetDataNode()->SetProperty( "framerate",mitk::FloatProperty::New(0.00001)); interactor->SetDesiredUpdateRate( 0.00001 ); interactor->SetStillUpdateRate( 0.00001 ); } if ( m_RenderWindowInitialized.find( renderWindow ) == m_RenderWindowInitialized.end() ) { m_RenderWindowInitialized.insert( renderWindow ); // mitk::RenderingManager::GetInstance()->SetNextLOD( 0, renderer ); mitk::RenderingManager::GetInstance()->SetShading( true, 0 ); mitk::RenderingManager::GetInstance()->SetShading( true, 1 ); //mitk::RenderingManager::GetInstance()->SetShading( true, 2 ); mitk::RenderingManager::GetInstance()->SetShadingValues( m_VolumePropertyHigh->GetAmbient(), m_VolumePropertyHigh->GetDiffuse(), m_VolumePropertyHigh->GetSpecular(), m_VolumePropertyHigh->GetSpecularPower()); mitk::RenderingManager::GetInstance()->SetClippingPlaneStatus(false); } this->SetClippingPlane( interactor ); } void mitk::VolumeDataVtkMapper3D::CreateDefaultTransferFunctions() { m_DefaultOpacityTransferFunction = vtkPiecewiseFunction::New(); m_DefaultOpacityTransferFunction->AddPoint( 0.0, 0.0 ); m_DefaultOpacityTransferFunction->AddPoint( 255.0, 0.8 ); m_DefaultOpacityTransferFunction->ClampingOn(); m_DefaultGradientTransferFunction = vtkPiecewiseFunction::New(); m_DefaultGradientTransferFunction->AddPoint( 0.0, 0.0 ); m_DefaultGradientTransferFunction->AddPoint( 255.0, 0.8 ); m_DefaultGradientTransferFunction->ClampingOn(); m_DefaultColorTransferFunction = vtkColorTransferFunction::New(); m_DefaultColorTransferFunction->AddRGBPoint( 0.0, 0.0, 0.0, 0.0 ); m_DefaultColorTransferFunction->AddRGBPoint( 127.5, 1, 1, 0.0 ); m_DefaultColorTransferFunction->AddRGBPoint( 255.0, 0.8, 0.2, 0 ); m_DefaultColorTransferFunction->ClampingOn(); } void mitk::VolumeDataVtkMapper3D::UpdateTransferFunctions( mitk::BaseRenderer *renderer ) { vtkPiecewiseFunction *opacityTransferFunction = NULL; vtkPiecewiseFunction *gradientTransferFunction = NULL; vtkColorTransferFunction *colorTransferFunction = NULL; mitk::LookupTableProperty::Pointer lookupTableProp; lookupTableProp = dynamic_cast(this->GetDataNode()->GetProperty("LookupTable")); mitk::TransferFunctionProperty::Pointer transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("TransferFunction")); if ( transferFunctionProp.IsNotNull() ) { opacityTransferFunction = transferFunctionProp->GetValue()->GetScalarOpacityFunction(); gradientTransferFunction = transferFunctionProp->GetValue()->GetGradientOpacityFunction(); colorTransferFunction = transferFunctionProp->GetValue()->GetColorTransferFunction(); } else if (lookupTableProp.IsNotNull() ) { lookupTableProp->GetLookupTable()->CreateOpacityTransferFunction(opacityTransferFunction); opacityTransferFunction->ClampingOn(); lookupTableProp->GetLookupTable()->CreateGradientTransferFunction(gradientTransferFunction); gradientTransferFunction->ClampingOn(); lookupTableProp->GetLookupTable()->CreateColorTransferFunction(colorTransferFunction); colorTransferFunction->ClampingOn(); } else { opacityTransferFunction = m_DefaultOpacityTransferFunction; gradientTransferFunction = m_DefaultGradientTransferFunction; colorTransferFunction = m_DefaultColorTransferFunction; float rgb[3]={1.0f,1.0f,1.0f}; // check for color prop and use it for rendering if it exists - if(GetColor(rgb, renderer)) + if(GetDataNode()->GetColor(rgb, renderer, "color")) { colorTransferFunction->AddRGBPoint( 0.0, 0.0, 0.0, 0.0 ); colorTransferFunction->AddRGBPoint( 127.5, rgb[0], rgb[1], rgb[2] ); colorTransferFunction->AddRGBPoint( 255.0, rgb[0], rgb[1], rgb[2] ); } } if (this->m_Mask) { opacityTransferFunction->AddPoint(0xffff, 0.0); } m_VolumePropertyLow->SetColor( colorTransferFunction ); m_VolumePropertyLow->SetScalarOpacity( opacityTransferFunction ); m_VolumePropertyLow->SetGradientOpacity( gradientTransferFunction ); m_VolumePropertyLow->SetInterpolationTypeToNearest(); m_VolumePropertyMed->SetColor( colorTransferFunction ); m_VolumePropertyMed->SetScalarOpacity( opacityTransferFunction ); m_VolumePropertyMed->SetGradientOpacity( gradientTransferFunction ); m_VolumePropertyMed->SetInterpolationTypeToNearest(); m_VolumePropertyHigh->SetColor( colorTransferFunction ); m_VolumePropertyHigh->SetScalarOpacity( opacityTransferFunction ); m_VolumePropertyHigh->SetGradientOpacity( gradientTransferFunction ); m_VolumePropertyHigh->SetInterpolationTypeToLinear(); } /* Shading enabled / disabled */ void mitk::VolumeDataVtkMapper3D::SetPreferences() { //LOD 0 /*if(mitk::RenderingManager::GetInstance()->GetShading(0)) { m_VolumePropertyLow->ShadeOn(); m_VolumePropertyLow->SetAmbient(mitk::RenderingManager::GetInstance()->GetShadingValues()[0]); m_VolumePropertyLow->SetDiffuse(mitk::RenderingManager::GetInstance()->GetShadingValues()[1]); m_VolumePropertyLow->SetSpecular(mitk::RenderingManager::GetInstance()->GetShadingValues()[2]); m_VolumePropertyLow->SetSpecularPower(mitk::RenderingManager::GetInstance()->GetShadingValues()[3]); } else*/ { m_VolumePropertyLow->ShadeOff(); } //LOD 1 /*if(mitk::RenderingManager::GetInstance()->GetShading(1)) { m_VolumePropertyMed->ShadeOn(); m_VolumePropertyMed->SetAmbient(mitk::RenderingManager::GetInstance()->GetShadingValues()[0]); m_VolumePropertyMed->SetDiffuse(mitk::RenderingManager::GetInstance()->GetShadingValues()[1]); m_VolumePropertyMed->SetSpecular(mitk::RenderingManager::GetInstance()->GetShadingValues()[2]); m_VolumePropertyMed->SetSpecularPower(mitk::RenderingManager::GetInstance()->GetShadingValues()[3]); } else*/ { m_VolumePropertyMed->ShadeOff(); } //LOD 2 /* if(mitk::RenderingManager::GetInstance()->GetShading(2)) { m_VolumePropertyHigh->ShadeOn(); //Shading Properties m_VolumePropertyHigh->SetAmbient(mitk::RenderingManager::GetInstance()->GetShadingValues()[0]); m_VolumePropertyHigh->SetDiffuse(mitk::RenderingManager::GetInstance()->GetShadingValues()[1]); m_VolumePropertyHigh->SetSpecular(mitk::RenderingManager::GetInstance()->GetShadingValues()[2]); m_VolumePropertyHigh->SetSpecularPower(mitk::RenderingManager::GetInstance()->GetShadingValues()[3]); } else { m_VolumePropertyHigh->ShadeOff(); } */ } /* Adds A Clipping Plane to the Mapper */ void mitk::VolumeDataVtkMapper3D::SetClippingPlane(vtkRenderWindowInteractor* interactor) { if(mitk::RenderingManager::GetInstance()->GetClippingPlaneStatus()) //if clipping plane is enabled { if(!m_PlaneSet) { m_PlaneWidget->SetInteractor(interactor); m_PlaneWidget->SetPlaceFactor(1.0); m_PlaneWidget->SetInput(m_UnitSpacingImageFilter->GetOutput()); m_PlaneWidget->OutlineTranslationOff(); //disables scaling of the bounding box m_PlaneWidget->ScaleEnabledOff(); //disables scaling of the bounding box m_PlaneWidget->DrawPlaneOff(); //clipping plane is transparent mitk::Image* input = const_cast(this->GetInput()); /*places the widget within the specified bounds*/ m_PlaneWidget->PlaceWidget( input->GetGeometry()->GetOrigin()[0],(input->GetGeometry()->GetOrigin()[0])+(input->GetDimension(0))*(input->GetVtkImageData()->GetSpacing()[0]), input->GetGeometry()->GetOrigin()[1],(input->GetGeometry()->GetOrigin()[1])+(input->GetDimension(1))*(input->GetVtkImageData()->GetSpacing()[1]), input->GetGeometry()->GetOrigin()[2],(input->GetGeometry()->GetOrigin()[2])+(input->GetDimension(2))*(input->GetVtkImageData()->GetSpacing()[2])); // m_T2DMapper->AddClippingPlane(m_ClippingPlane); m_HiResMapper->AddClippingPlane(m_ClippingPlane); } m_PlaneWidget->GetPlane(m_ClippingPlane); m_PlaneSet = true; } else //if clippingplane is disabled { if(m_PlaneSet) //if plane exists { DelClippingPlane(); } } } /* Removes the clipping plane */ void mitk::VolumeDataVtkMapper3D::DelClippingPlane() { // m_T2DMapper->RemoveAllClippingPlanes(); m_HiResMapper->RemoveAllClippingPlanes(); m_PlaneSet = false; } -void mitk::VolumeDataVtkMapper3D::ApplyProperties(vtkActor* /*actor*/, mitk::BaseRenderer* /*renderer*/) -{ - -} void mitk::VolumeDataVtkMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "volumerendering", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "volumerendering configuration", mitk::VtkVolumeRenderingProperty::New( 1 ), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite ); mitk::Image::Pointer image = dynamic_cast(node->GetData()); if(image.IsNotNull() && image->IsInitialized()) { if((overwrite) || (node->GetProperty("levelwindow", renderer)==NULL)) { mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); mitk::LevelWindow levelwindow; levelwindow.SetAuto( image ); levWinProp->SetLevelWindow( levelwindow ); node->SetProperty( "levelwindow", levWinProp, renderer ); } //This mapper used to set a default lut "LookupTable" for images. However, this will //overwrite the default lut of the 2D image mapper. Thus, this property here is renamed. /* if((overwrite) || (node->GetProperty("Volume.LookupTable", renderer)==NULL)) { // add a default rainbow lookup table for color mapping mitk::LookupTable::Pointer mitkLut = mitk::LookupTable::New(); vtkLookupTable* vtkLut = mitkLut->GetVtkLookupTable(); vtkLut->SetHueRange(0.6667, 0.0); vtkLut->SetTableRange(0.0, 20.0); vtkLut->Build(); mitk::LookupTableProperty::Pointer mitkLutProp = mitk::LookupTableProperty::New(); mitkLutProp->SetLookupTable(mitkLut); node->SetProperty( "Volume.LookupTable", mitkLutProp ); }*/ if((overwrite) || (node->GetProperty("TransferFunction", renderer)==NULL)) { // add a default transfer function mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(tf); tfInit->SetTransferFunctionMode(0); node->SetProperty ( "TransferFunction", mitk::TransferFunctionProperty::New ( tf.GetPointer() ) ); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } bool mitk::VolumeDataVtkMapper3D::IsLODEnabled( mitk::BaseRenderer * /*renderer*/ ) const { return false; // Volume mapper is LOD enabled if volumerendering is enabled /* return dynamic_cast(GetDataNode()->GetProperty("volumerendering",renderer)) != NULL && dynamic_cast(GetDataNode()->GetProperty("volumerendering",renderer))->GetValue() == true; */ } void mitk::VolumeDataVtkMapper3D::EnableMask() { if (!this->m_Mask) { const Image *orig_image = this->GetInput(); unsigned int *dimensions = orig_image->GetDimensions(); this->m_Mask = vtkImageData::New(); this->m_Mask->SetDimensions(dimensions[0], dimensions[1], dimensions[2]); this->m_Mask->SetScalarTypeToUnsignedChar(); this->m_Mask->SetNumberOfScalarComponents(1); this->m_Mask->AllocateScalars(); unsigned char *mask_data = static_cast(this->m_Mask->GetScalarPointer()); unsigned int size = dimensions[0] * dimensions[1] * dimensions[2]; for (unsigned int i = 0u; i < size; ++i) { *mask_data++ = 1u; } this->m_ImageMaskFilter->SetMaskInput(this->m_Mask); this->m_ImageMaskFilter->Modified(); } } void mitk::VolumeDataVtkMapper3D::DisableMask() { if (this->m_Mask) { this->m_Mask->Delete(); this->m_Mask = 0; } } mitk::Image::Pointer mitk::VolumeDataVtkMapper3D::GetMask() { if (this->m_Mask) { Image::Pointer mask = Image::New(); mask->Initialize(this->m_Mask); mask->SetImportVolume(this->m_Mask->GetScalarPointer(), 0, 0, Image::ReferenceMemory); mask->SetGeometry(this->GetInput()->GetGeometry()); return mask; } return 0; } void mitk::VolumeDataVtkMapper3D::UpdateMask() { if (this->m_Mask) { this->m_ImageMaskFilter->Modified(); } } bool mitk::VolumeDataVtkMapper3D::SetMask(const mitk::Image* mask) { if (this->m_Mask) { if ( (mask->GetPixelType().GetTypeId() == typeid(unsigned char)) &&(mask->GetPixelType().GetPixelTypeId() == itk::ImageIOBase::SCALAR )) { Image *img = const_cast(mask); this->m_Mask->DeepCopy(img->GetVtkImageData()); this->m_ImageMaskFilter->Modified(); return true; } } return false; } diff --git a/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.h b/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.h index 2ea5461dd1..4cf0ec6e99 100644 --- a/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.h +++ b/Core/Code/Rendering/mitkVolumeDataVtkMapper3D.h @@ -1,150 +1,148 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKVOLUMEDATAVTKMAPPER3D_H_HEADER_INCLUDED #define MITKVOLUMEDATAVTKMAPPER3D_H_HEADER_INCLUDED #include -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include "mitkBaseRenderer.h" #include "mitkImage.h" #include #include #include #include #include #include #include class vtkAssembly; class vtkVolumeRayCastMapper; class vtkFixedPointVolumeRayCastMapper; class vtkVolumeTextureMapper2D; class vtkVolumeMapper; class vtkVolume; class vtkObject; class vtkImageShiftScale; class vtkImageChangeInformation; class vtkLODProp3D; class vtkImageResample; class vtkCubeSource; class vtkPolyDataMapper; class vtkActor; namespace mitk { /************************************************************************/ /* Properties that influence the mapper are: * * - \b "level window": for the level window of the volume data * - \b "LookupTable" : for the lookup table of the volume data * - \b "TransferFunction" (mitk::TransferFunctionProperty): for the used transfer function of the volume data ************************************************************************/ //##Documentation //## @brief Vtk-based mapper for VolumeData //## //## @ingroup Mapper -class MITK_CORE_EXPORT VolumeDataVtkMapper3D : public VtkMapper3D +class MITK_CORE_EXPORT VolumeDataVtkMapper3D : public VtkMapper { public: - mitkClassMacro(VolumeDataVtkMapper3D, VtkMapper3D); + mitkClassMacro(VolumeDataVtkMapper3D, VtkMapper); itkNewMacro(Self); virtual const mitk::Image* GetInput(); - virtual void ApplyProperties(vtkActor* actor, mitk::BaseRenderer* renderer); - virtual void EnableMask(); virtual void DisableMask(); Image::Pointer GetMask(); bool SetMask(const Image* mask); virtual void UpdateMask(); static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); /** Returns true if this Mapper currently allows for Level-of-Detail rendering. * This reflects whether this Mapper currently invokes StartEvent, EndEvent, and * ProgressEvent on BaseRenderer. */ virtual bool IsLODEnabled( BaseRenderer *renderer = NULL ) const; virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); protected: VolumeDataVtkMapper3D(); virtual ~VolumeDataVtkMapper3D(); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); void CreateDefaultTransferFunctions(); void UpdateTransferFunctions( mitk::BaseRenderer *renderer ); void SetPreferences(); void SetClippingPlane(vtkRenderWindowInteractor* interactor); void DelClippingPlane(); vtkImageShiftScale* m_ImageCast; vtkImageChangeInformation* m_UnitSpacingImageFilter; vtkVolumeProperty* m_VolumePropertyLow; vtkVolumeProperty* m_VolumePropertyMed; vtkVolumeProperty* m_VolumePropertyHigh; vtkVolumeTextureMapper2D* m_T2DMapper; vtkVolumeRayCastMapper* m_HiResMapper; vtkImageResample* m_Resampler; vtkLODProp3D* m_VolumeLOD; vtkCubeSource *m_BoundingBox; vtkPolyDataMapper *m_BoundingBoxMapper; vtkActor *m_BoundingBoxActor; vtkAssembly *m_Prop3DAssembly; vtkPlane* m_ClippingPlane; vtkImplicitPlaneWidget* m_PlaneWidget; vtkImageData *m_Mask; vtkImageMask *m_ImageMaskFilter; vtkPiecewiseFunction *m_DefaultOpacityTransferFunction; vtkPiecewiseFunction *m_DefaultGradientTransferFunction; vtkColorTransferFunction *m_DefaultColorTransferFunction; int m_LowResID; int m_MedResID; int m_HiResID; bool m_PlaneSet; double m_PlaneNormalA; double m_PlaneNormalB; double m_PlaneNormalC; std::set< vtkRenderWindow * > m_RenderWindowInitialized; }; } // namespace mitk #endif /* MITKVOLUMEDATAVTKMAPPER3D_H_HEADER_INCLUDED */ diff --git a/Core/Code/Rendering/mitkVtkMapper.cpp b/Core/Code/Rendering/mitkVtkMapper.cpp new file mode 100644 index 0000000000..a272fba01e --- /dev/null +++ b/Core/Code/Rendering/mitkVtkMapper.cpp @@ -0,0 +1,129 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkVtkMapper.h" + +mitk::VtkMapper::VtkMapper() +{ +} + +mitk::VtkMapper::~VtkMapper() +{ +} + +void mitk::VtkMapper::MitkRender(mitk::BaseRenderer* renderer, mitk::VtkPropRenderer::RenderType type){ + + switch(type) + { + case mitk::VtkPropRenderer::Opaque: this->MitkRenderOpaqueGeometry(renderer); break; + case mitk::VtkPropRenderer::Translucent: this->MitkRenderTranslucentGeometry(renderer); break; + case mitk::VtkPropRenderer::Overlay: this->MitkRenderOverlay(renderer); break; + case mitk::VtkPropRenderer::Volumetric: this->MitkRenderVolumetricGeometry(renderer); break; + } +} + +bool mitk::VtkMapper::IsVtkBased() const +{ + return true; +} + +void mitk::VtkMapper::MitkRenderOverlay(BaseRenderer* renderer) +{ + + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + if ( !visible) return; + + if ( this->GetVtkProp(renderer)->GetVisibility() ) + { + GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); + } +} + +void mitk::VtkMapper::MitkRenderOpaqueGeometry(BaseRenderer* renderer) +{ + bool visible = true; + + GetDataNode()->GetVisibility(visible, renderer, "visible"); + if ( !visible) return; + + if ( this->GetVtkProp(renderer)->GetVisibility() ) + { + GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); + } +} + +void mitk::VtkMapper::MitkRenderTranslucentGeometry(BaseRenderer* renderer) +{ + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + if ( !visible) return; + + if ( this->GetVtkProp(renderer)->GetVisibility() ) + { + GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); + } +} + +void mitk::VtkMapper::MitkRenderVolumetricGeometry(BaseRenderer* renderer) +{ + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + if ( !visible) return; + + if ( GetVtkProp(renderer)->GetVisibility() ) + { + GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); + } +} + +bool mitk::VtkMapper::HasVtkProp( const vtkProp *prop, BaseRenderer *renderer ) +{ + vtkProp *myProp = this->GetVtkProp( renderer ); + + // TODO: check if myProp is a vtkAssembly and if so, check if prop is contained in its leafs + return ( prop == myProp ); +} + +void mitk::VtkMapper::SetVtkMapperImmediateModeRendering(vtkMapper *mapper) +{ + if(mapper) + mapper->SetImmediateModeRendering(mitk::VtkPropRenderer::useImmediateModeRendering()); +} + +void mitk::VtkMapper::UpdateVtkTransform(mitk::BaseRenderer *renderer) +{ + vtkLinearTransform * vtktransform = GetDataNode()->GetVtkTransform(this->GetTimestep()); + + vtkProp3D *prop = dynamic_cast( GetVtkProp(renderer) ); + if(prop) + prop->SetUserTransform(vtktransform); +} + +void mitk::VtkMapper::ApplyColorAndOpacityProperties(BaseRenderer* renderer, vtkActor* actor) +{ + float rgba[4]={1.0f,1.0f,1.0f,1.0f}; + DataNode * node = GetDataNode(); + + // check for color prop and use it for rendering if it exists + node->GetColor(rgba, renderer, "color"); + // check for opacity prop and use it for rendering if it exists + node->GetOpacity(rgba[3], renderer, "opacity"); + + double drgba[4]={rgba[0],rgba[1],rgba[2],rgba[3]}; + actor->GetProperty()->SetColor(drgba); + actor->GetProperty()->SetOpacity(drgba[3]); +} diff --git a/Core/Code/Rendering/mitkVtkMapper.h b/Core/Code/Rendering/mitkVtkMapper.h new file mode 100644 index 0000000000..789b1f52ad --- /dev/null +++ b/Core/Code/Rendering/mitkVtkMapper.h @@ -0,0 +1,145 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// change number +#ifndef VTKMAPPER_H_HEADER_INCLUDED_C1C5453B +#define VTKMAPPER_H_HEADER_INCLUDED_C1C5453B + +#include +#include "mitkMapper.h" +#include "mitkBaseRenderer.h" +#include "mitkDataNode.h" +#include "mitkVtkPropRenderer.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +class vtkProp; +class vtkProp3D; +class vtkActor; + +namespace mitk { + +/** \brief Base class of all Vtk Mappers in order to display primitives +* by exploiting Vtk functionality. +* +* Rendering of opaque, translucent or volumetric geometry and overlays +* is done in consecutive render passes. +* +* \ingroup Mapper +*/ +class MITK_CORE_EXPORT VtkMapper : public Mapper +{ + public: + mitkClassMacro(VtkMapper,Mapper); + + virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) = 0; + + /** \brief Re-issues all drawing commands required to describe + * the entire scene each time a new frame is required, + * regardless of actual changes. + */ + static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); + + /** + * \brief Returns whether this is an vtk-based mapper + * @deprecated All mappers of superclass VTKMapper are vtk based, use a dynamic_cast instead + */ + DEPRECATED( virtual bool IsVtkBased() const ); + + + /** \brief Determines which geometry should be rendered + * (opaque, translucent, volumetric, overlay) + * and calls the appropriate function. + * + * Called by mitk::VtkPropRenderer::Render + */ + void MitkRender(mitk::BaseRenderer* renderer, mitk::VtkPropRenderer::RenderType type); + + /** \brief Checks visibility and renders the overlay */ + virtual void MitkRenderOverlay(BaseRenderer* renderer); + + /** \brief Checks visibility and renders untransparent geometry */ + virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer); + + /** \brief Checks visiblity and renders transparent geometry */ + virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer); + + /** \brief Checks visibility and renders volumes */ + virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer); + + /** \brief Returns true if this mapper owns the specified vtkProp for + * the given BaseRenderer. + * + * Note: returns false by default; should be implemented for VTK-based + * Mapper subclasses. */ + virtual bool HasVtkProp( const vtkProp *prop, BaseRenderer *renderer ); + + /** \brief Set the vtkTransform of the m_Prop3D for + * the current time step of \a renderer + * + * Called by mitk::VtkPropRenderer::Update before rendering + */ + virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer); + + /** + * \brief Apply color and opacity properties read from the PropertyList + * @deprecated Use ApplyColorAndOpacityProperties(mitk::BaseRenderer* renderer, vtkActor * actor) instead + */ + DEPRECATED(inline virtual void ApplyProperties(vtkActor* actor, mitk::BaseRenderer* renderer) + { + ApplyColorAndOpacityProperties(renderer, actor); + }); + + /** + * \brief Apply color and opacity properties read from the PropertyList. + * Called by mapper subclasses. + */ + virtual void ApplyColorAndOpacityProperties(mitk::BaseRenderer* renderer, vtkActor * actor); + + /** + * \brief Release vtk-based graphics resources that are being consumed by this mapper. + * The parameter window could be used to determine which graphic + * resources to releases. Must be overwritten in individual subclasses + * if vtkProps are used. + */ + virtual void ReleaseGraphicsResources(vtkWindow* /*renWin*/) { }; + + protected: + + /** constructor */ + VtkMapper(); + + /** virtual destructor in order to derive from this class */ + virtual ~VtkMapper(); + + private: + + /** copy constructor */ + VtkMapper( const VtkMapper &); + + /** assignment operator */ + VtkMapper & operator=(const VtkMapper &); + +}; +} // namespace mitk +#endif /* VTKMAPPER_H_HEADER_INCLUDED_C1C5453B */ diff --git a/Core/Code/Rendering/mitkVtkMapper2D.cpp b/Core/Code/Rendering/mitkVtkMapper2D.cpp deleted file mode 100644 index 61761927b9..0000000000 --- a/Core/Code/Rendering/mitkVtkMapper2D.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - - -#include "mitkVtkMapper2D.h" - -mitk::VtkMapper2D::VtkMapper2D() -{ - -} - - -mitk::VtkMapper2D::~VtkMapper2D() -{ -} - diff --git a/Core/Code/Rendering/mitkVtkMapper2D.h b/Core/Code/Rendering/mitkVtkMapper2D.h index 90134f196d..f9db3be352 100644 --- a/Core/Code/Rendering/mitkVtkMapper2D.h +++ b/Core/Code/Rendering/mitkVtkMapper2D.h @@ -1,55 +1,32 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef BASEVTKMAPPER2D_H_HEADER_INCLUDED #define BASEVTKMAPPER2D_H_HEADER_INCLUDED -#include "mitkMapper2D.h" - -class vtkProp; +#include "mitkVtkMapper.h" namespace mitk { - //##Documentation - //## @brief Base class of all vtk-based 2D-Mappers - //## - //## Those must implement the abstract - //## method vtkProp* GetProp(). - //## @ingroup Mapper - class MITK_CORE_EXPORT VtkMapper2D : public Mapper2D - { - public: - mitkClassMacro(VtkMapper2D,Mapper2D); - virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) = 0; - - /** - * \brief Returns whether this is an vtk-based mapper - */ - virtual bool IsVtkBased() const { return true; } - - protected: - VtkMapper2D(); - - virtual ~VtkMapper2D(); - - }; + // typedef allows integration of mappers into the new mapper architecture + // @deprecated Use VtkMapper instead. + DEPRECATED(typedef VtkMapper VtkMapper2D); } // namespace mitk - #endif /* BASEVTKMAPPER2D_H_HEADER_INCLUDED */ diff --git a/Core/Code/Rendering/mitkVtkMapper3D.cpp b/Core/Code/Rendering/mitkVtkMapper3D.cpp deleted file mode 100644 index 8c6bb0ddb5..0000000000 --- a/Core/Code/Rendering/mitkVtkMapper3D.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/*=================================================================== - -The Medical Imaging Interaction Toolkit (MITK) - -Copyright (c) German Cancer Research Center, -Division of Medical and Biological Informatics. -All rights reserved. - -This software is distributed WITHOUT ANY WARRANTY; without -even the implied warranty of MERCHANTABILITY or FITNESS FOR -A PARTICULAR PURPOSE. - -See LICENSE.txt or http://www.mitk.org for details. - -===================================================================*/ - - -#include "mitkVtkMapper3D.h" -#include "mitkDataNode.h" -#include "mitkProperties.h" -#include "mitkAnnotationProperty.h" -#include "mitkVtkPropRenderer.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -namespace mitk -{ - -VtkMapper3D::VtkMapper3D() -{ -} - - -VtkMapper3D::~VtkMapper3D() -{ -} - -void VtkMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *mapper) -{ - if(mapper) - mapper->SetImmediateModeRendering(mitk::VtkPropRenderer::useImmediateModeRendering()); -} - - -void VtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer *renderer) -{ - vtkLinearTransform * vtktransform = GetDataNode()->GetVtkTransform(this->GetTimestep()); - - vtkProp3D *prop = dynamic_cast( GetVtkProp(renderer) ); - if(prop) - prop->SetUserTransform(vtktransform); -} - - -void VtkMapper3D::MitkRenderOpaqueGeometry(BaseRenderer* renderer) -{ - if ( this->IsVisible( renderer )==false ) - return; - - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); - } -} - -void VtkMapper3D::MitkRenderTranslucentGeometry(BaseRenderer* renderer) -{ - if ( this->IsVisible(renderer)==false ) - return; - - /* if(dynamic_cast(m_Prop3D) != NULL) - { - if( dynamic_cast(GetDataNode()-> - GetProperty("volumerendering",renderer).GetPointer())==NULL || - dynamic_cast(GetDataNode()-> - GetProperty("volumerendering",renderer).GetPointer())->GetValue() == false) - return; - }*/ - - if ( this->GetVtkProp(renderer)->GetVisibility() ) - this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); - -} - - -void VtkMapper3D::MitkRenderVolumetricGeometry(BaseRenderer* renderer) -{ - if(IsVisible(renderer)==false) - return; - - /* if(dynamic_cast(m_Prop3D) != NULL) - { - if( dynamic_cast(GetDataNode()-> - GetProperty("volumerendering",renderer).GetPointer())==NULL || - dynamic_cast(GetDataNode()-> - GetProperty("volumerendering",renderer).GetPointer())->GetValue() == false) - return; - }*/ - - if ( GetVtkProp(renderer)->GetVisibility() ) - GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); - -} - - -void VtkMapper3D::MitkRenderOverlay(BaseRenderer* renderer) -{ - if ( this->IsVisible(renderer)==false ) - return; - - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); - } - - // Render annotations as overlay -/* - m_LabelActorCollection->InitTraversal(); - vtkProp3D *labelActor; - for ( m_LabelActorCollection->InitTraversal(); - (labelActor = m_LabelActorCollection->GetNextProp3D()); ) - { - if ( labelActor->GetVisibility() ) - labelActor->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); - } - */ -} - - -void VtkMapper3D::ApplyProperties(vtkActor* actor, BaseRenderer* renderer) -{ - float rgba[4]={1.0f,1.0f,1.0f,1.0f}; - // check for color prop and use it for rendering if it exists - this->GetColor(rgba, renderer); - // check for opacity prop and use it for rendering if it exists - this->GetOpacity(rgba[3], renderer); - - double drgba[4]={rgba[0],rgba[1],rgba[2],rgba[3]}; - actor->GetProperty()->SetColor(drgba); - actor->GetProperty()->SetOpacity(drgba[3]); - - // Add annotations to assembly, if any (camera (renderer) must be present) - if ( renderer != NULL ) - { - // Check whether one or more AnnotationProperty objects have been defined for - // this node. Check both renderer specific and global property lists, since - // properties in both should be considered. - //const PropertyList::PropertyMap *rendererProperties = this->GetDataNode()->GetPropertyList( renderer )->GetMap(); - //const PropertyList::PropertyMap *globalProperties = this->GetDataNode()->GetPropertyList( NULL )->GetMap(); - - // Add clipping planes (if any) -/* - m_LabelActorCollection->RemoveAllItems(); - - PropertyList::PropertyMap::const_iterator it; - for ( it = rendererProperties->begin(); it != rendererProperties->end(); ++it ) - { - this->CheckForAnnotationProperty( (*it).second.first.GetPointer(), renderer ); - } - - for ( it = globalProperties->begin(); it != globalProperties->end(); ++it ) - { - this->CheckForAnnotationProperty( (*it).second.first.GetPointer(), renderer ); - } - */ - } -} - -/* -void VtkMapper3D::CheckForAnnotationProperty( mitk::BaseProperty *property, BaseRenderer *renderer ) -{ - AnnotationProperty *annotationProperty = - dynamic_cast< AnnotationProperty * >( property ); - - if ( annotationProperty != NULL ) - { - vtkVectorText *labelText = vtkVectorText::New(); - vtkPolyDataMapper *labelMapper = vtkPolyDataMapper::New(); - labelMapper->SetInput( labelText->GetOutput() ); - - vtkFollower *labelFollower = vtkFollower::New(); - labelFollower->SetMapper( labelMapper ); - labelFollower->SetCamera( renderer->GetVtkRenderer()->GetActiveCamera() ); - - labelFollower->SetScale( 2.5, 2.5, 2.5 ); - labelFollower->GetProperty()->SetColor( 1.0, 0.2, 0.1 ); - - labelText->SetText( annotationProperty->GetLabel() ); - - const Point3D &pos = annotationProperty->GetPosition(); - - Geometry3D *geometry = m_DataNode->GetData()->GetGeometry(); - - Point3D transformedPos; - geometry->IndexToWorld( pos, transformedPos ); - - labelFollower->SetPosition( transformedPos[0], transformedPos[1], transformedPos[2] ); - - //labelFollower->SetUserTransform( - // m_DataNode->GetData()->GetGeometry()->GetVtkTransform() ); - - m_LabelActorCollection->AddItem( labelFollower ); - } -} -*/ - -void VtkMapper3D::ReleaseGraphicsResources(vtkWindow * /*renWin*/) -{ -/* - if(m_Prop3D) - m_Prop3D->ReleaseGraphicsResources(renWin); -*/ -} - - -bool VtkMapper3D::HasVtkProp( const vtkProp *prop, BaseRenderer *renderer ) -{ - vtkProp *myProp = this->GetVtkProp( renderer ); - - // TODO: check if myProp is a vtkAssembly and if so, check if prop is contained in its leafs - return ( prop == myProp ); -} - - - -} // namespace - diff --git a/Core/Code/Rendering/mitkVtkMapper3D.h b/Core/Code/Rendering/mitkVtkMapper3D.h index 3c691709ed..f31560ec0f 100644 --- a/Core/Code/Rendering/mitkVtkMapper3D.h +++ b/Core/Code/Rendering/mitkVtkMapper3D.h @@ -1,112 +1,31 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef BASEVTKMAPPER3D_H_HEADER_INCLUDED #define BASEVTKMAPPER3D_H_HEADER_INCLUDED -#include -#include "mitkMapper.h" -#include "mitkMapper3D.h" -#include "mitkBaseRenderer.h" -#include "vtkMapper.h" - -class vtkProp; -class vtkProp3D; -class vtkActor; -class vtkProp3DCollection; +#include "mitkVtkMapper.h" namespace mitk { -//##Documentation -//## @brief Base class of all vtk-based 3D-Mappers -//## -//## GetProp() returns m_Prop3D, which should be -//## initialized by sub-classes (e.g., by setting -//## it to an vtkActor). -//## @ingroup Mapper -class MITK_CORE_EXPORT VtkMapper3D : public Mapper3D -{ -public: - mitkClassMacro(VtkMapper3D, Mapper3D); - - virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer) = 0; - - static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); - - virtual void MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer); - virtual void MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer); - virtual void MitkRenderOverlay(mitk::BaseRenderer* renderer); - - - virtual void MitkRenderVolumetricGeometry(mitk::BaseRenderer* renderer); - - //##Documentation - //## @brief Set the vtkTransform of the m_Prop3D for - //## the current time step of \a renderer - //## - //## Called by mitk::VtkPropRenderer::Update before rendering - //## - virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer); - - //##Documentation - //## @brief Apply color and opacity read from the PropertyList - virtual void ApplyProperties(vtkActor* actor, mitk::BaseRenderer* renderer); - - /** - * \brief Release vtk-based graphics resources. Must be overwritten in - * subclasses if vtkProps additional to m_Prop3D are used. - */ - virtual void ReleaseGraphicsResources(vtkWindow *renWin); - - - /** \brief Returns true if this mapper owns the specified vtkProp for - * the given BaseRenderer. - * - * Note: returns false by default; should be implemented for VTK-based - * Mapper subclasses. */ - virtual bool HasVtkProp( const vtkProp *prop, BaseRenderer *renderer ); - - /** - * \brief Returns whether this is an vtk-based mapper - */ - virtual bool IsVtkBased() const { return true; } - -protected: - VtkMapper3D(); - - virtual ~VtkMapper3D(); - - /** Checks whether the specified property is a AnnotationProperty and if yes, - * adds it to m_LabelActorCollection (internal method). */ - // virtual void CheckForAnnotationProperty( mitk::BaseProperty *property, BaseRenderer *renderer ); - -public: - - itkGetObjectMacro(Geometry,Geometry3D); - itkSetObjectMacro(Geometry,Geometry3D); - -protected: - Geometry3D::Pointer m_Geometry; - LevelWindow m_LevelWindow; - - //vtkProp3D *m_Prop3D; - //vtkProp3DCollection *m_LabelActorCollection; -}; + // typedef allows integration of mappers into the new mapper architecture + // @deprecated Use VtkMapper instead + DEPRECATED(typedef VtkMapper VtkMapper3D); } // namespace mitk #endif /* BASEVTKMAPPER3D_H_HEADER_INCLUDED */ diff --git a/Core/Code/Rendering/mitkVtkPropRenderer.cpp b/Core/Code/Rendering/mitkVtkPropRenderer.cpp index 185ef02450..af3f9d444e 100644 --- a/Core/Code/Rendering/mitkVtkPropRenderer.cpp +++ b/Core/Code/Rendering/mitkVtkPropRenderer.cpp @@ -1,926 +1,927 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkVtkPropRenderer.h" // MAPPERS #include "mitkMapper.h" #include "mitkImageVtkMapper2D.h" -#include "mitkVtkMapper2D.h" -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" +#include "mitkGLMapper.h" #include "mitkGeometry2DDataVtkMapper3D.h" #include "mitkPointSetGLMapper2D.h" #include "mitkImageSliceSelector.h" #include "mitkRenderingManager.h" #include "mitkGL.h" #include "mitkGeometry3D.h" #include "mitkDisplayGeometry.h" #include "mitkLevelWindow.h" #include "mitkCameraController.h" #include "mitkVtkInteractorCameraController.h" #include "mitkPlaneGeometry.h" #include "mitkProperties.h" #include "mitkSurface.h" #include "mitkNodePredicateDataType.h" #include "mitkVtkInteractorStyle.h" // VTK #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::VtkPropRenderer::VtkPropRenderer( const char* name, vtkRenderWindow * renWin, mitk::RenderingManager* rm ) : BaseRenderer(name,renWin, rm), m_VtkMapperPresent(false), m_NewRenderer(true), m_CameraInitializedForMapperID(0) { didCount=false; m_WorldPointPicker = vtkWorldPointPicker::New(); m_PointPicker = vtkPointPicker::New(); m_PointPicker->SetTolerance( 0.0025 ); m_CellPicker = vtkCellPicker::New(); m_CellPicker->SetTolerance( 0.0025 ); mitk::Geometry2DDataVtkMapper3D::Pointer geometryMapper = mitk::Geometry2DDataVtkMapper3D::New(); m_CurrentWorldGeometry2DMapper = geometryMapper; m_CurrentWorldGeometry2DNode->SetMapper(2, geometryMapper); m_LightKit = vtkLightKit::New(); m_LightKit->AddLightsToRenderer(m_VtkRenderer); m_PickingMode = WorldPointPicking; m_TextRenderer = vtkRenderer::New(); m_TextRenderer->SetRenderWindow(renWin); m_TextRenderer->SetInteractive(0); m_TextRenderer->SetErase(0); } /*! \brief Destructs the VtkPropRenderer. */ mitk::VtkPropRenderer::~VtkPropRenderer() { // Workaround for GLDisplayList Bug { m_MapperID=0; checkState(); } if (m_LightKit != NULL) m_LightKit->Delete(); if (m_VtkRenderer!=NULL) { m_CameraController = NULL; m_VtkRenderer->Delete(); m_VtkRenderer = NULL; } else m_CameraController = NULL; if (m_WorldPointPicker != NULL) m_WorldPointPicker->Delete(); if (m_PointPicker != NULL) m_PointPicker->Delete(); if (m_CellPicker != NULL) m_CellPicker->Delete(); if (m_TextRenderer != NULL) m_TextRenderer->Delete(); } void mitk::VtkPropRenderer::SetDataStorage( mitk::DataStorage* storage ) { if ( storage == NULL ) return; BaseRenderer::SetDataStorage(storage); static_cast(m_CurrentWorldGeometry2DMapper.GetPointer())->SetDataStorageForTexture( m_DataStorage.GetPointer() ); // Compute the geometry from the current data tree bounds and set it as world geometry this->SetWorldGeometryToDataStorageBounds(); } bool mitk::VtkPropRenderer::SetWorldGeometryToDataStorageBounds() { if ( m_DataStorage.IsNull() ) return false; //initialize world geometry mitk::TimeSlicedGeometry::Pointer geometry = m_DataStorage->ComputeVisibleBoundingGeometry3D( NULL, "includeInBoundingBox" ); if ( geometry.IsNull() ) return false; this->SetWorldGeometry(geometry); //this->GetDisplayGeometry()->SetSizeInDisplayUnits( this->m_TextRenderer->GetRenderWindow()->GetSize()[0], this->m_TextRenderer->GetRenderWindow()->GetSize()[1] ); this->GetDisplayGeometry()->Fit(); this->GetVtkRenderer()->ResetCamera(); this->Modified(); return true; } /*! \brief Called by the vtkMitkRenderProp in order to start MITK rendering process. */ int mitk::VtkPropRenderer::Render(mitk::VtkPropRenderer::RenderType type) { // Do we have objects to render? if ( this->GetEmptyWorldGeometry()) return 0; if ( m_DataStorage.IsNull()) return 0; // Update mappers and prepare mapper queue if (type == VtkPropRenderer::Opaque) this->PrepareMapperQueue(); //go through the generated list and let the sorted mappers paint bool lastVtkBased = true; //bool sthVtkBased = false; for(MappersMapType::iterator it = m_MappersMap.begin(); it != m_MappersMap.end(); it++) { Mapper * mapper = (*it).second; - if((mapper->IsVtkBased() == true) ) + + VtkMapper* vtkmapper = dynamic_cast(mapper); + + if(vtkmapper) { //sthVtkBased = true; - mitk::VtkMapper3D::Pointer vtkMapper = dynamic_cast(mapper); - if(vtkMapper) - { - vtkMapper->GetVtkProp(this)->SetAllocatedRenderTime(5000,GetVtkRenderer()); //B/ ToDo: rendering time calculation - //vtkMapper->GetVtkProp(this)->PokeMatrix(NULL); //B/ ToDo ??: VtkUserTransform - } - if(lastVtkBased == false) + if(!lastVtkBased) { Disable2DOpenGL(); lastVtkBased = true; } } else - if((mapper->IsVtkBased() == false) && (lastVtkBased == true)) + if(lastVtkBased) { Enable2DOpenGL(); lastVtkBased = false; } - switch(type) - { - case mitk::VtkPropRenderer::Opaque: mapper->MitkRenderOpaqueGeometry(this); break; - case mitk::VtkPropRenderer::Translucent: mapper->MitkRenderTranslucentGeometry(this); break; - case mitk::VtkPropRenderer::Overlay: mapper->MitkRenderOverlay(this); break; - case mitk::VtkPropRenderer::Volumetric: mapper->MitkRenderVolumetricGeometry(this); break; - } + mapper->MitkRender(this, type); + } if (lastVtkBased == false) Disable2DOpenGL(); // Render text if (type == VtkPropRenderer::Overlay) { if (m_TextCollection.size() > 0) { for (TextMapType::iterator it = m_TextCollection.begin(); it != m_TextCollection.end() ; it++) m_TextRenderer->AddViewProp((*it).second); m_TextRenderer->Render(); } } return 1; } /*! \brief PrepareMapperQueue iterates the datatree PrepareMapperQueue iterates the datatree in order to find mappers which shall be rendered. Also, it sortes the mappers wrt to their layer. */ void mitk::VtkPropRenderer::PrepareMapperQueue() { // variable for counting LOD-enabled mappers m_NumberOfVisibleLODEnabledMappers = 0; // Do we have to update the mappers ? if ( m_LastUpdateTime < GetMTime() || m_LastUpdateTime < GetDisplayGeometry()->GetMTime() ) { Update(); } else if (m_MapperID>=1 && m_MapperID < 6) Update(); // remove all text properties before mappers will add new ones m_TextRenderer->RemoveAllViewProps(); for ( unsigned int i=0; iDelete(); } m_TextCollection.clear(); // clear priority_queue m_MappersMap.clear(); int mapperNo = 0; //DataStorage if( m_DataStorage.IsNull() ) return; DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for (DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); it != allObjects->End(); ++it) { DataNode::Pointer node = it->Value(); if ( node.IsNull() ) continue; mitk::Mapper::Pointer mapper = node->GetMapper(m_MapperID); if ( mapper.IsNull() ) continue; + bool visible = true; + node->GetVisibility(visible, this, "visible"); + // The information about LOD-enabled mappers is required by RenderingManager - if ( mapper->IsLODEnabled( this ) && mapper->IsVisible( this ) ) + if ( mapper->IsLODEnabled( this ) && visible ) { ++m_NumberOfVisibleLODEnabledMappers; } // mapper without a layer property get layer number 1 int layer = 1; node->GetIntProperty("layer", layer, this); int nr = (layer<<16) + mapperNo; m_MappersMap.insert( std::pair< int, Mapper * >( nr, mapper ) ); mapperNo++; } } /*! \brief Enable2DOpenGL() and Disable2DOpenGL() are used to switch between 2D rendering (orthographic projection) and 3D rendering (perspective projection) */ void mitk::VtkPropRenderer::Enable2DOpenGL() { GLint iViewport[4]; // Get a copy of the viewport glGetIntegerv( GL_VIEWPORT, iViewport ); // Save a copy of the projection matrix so that we can restore it // when it's time to do 3D rendering again. glMatrixMode( GL_PROJECTION ); glPushMatrix(); glLoadIdentity(); // Set up the orthographic projection glOrtho( iViewport[0], iViewport[0]+iViewport[2], iViewport[1], iViewport[1]+iViewport[3], -1.0, 1.0 ); glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glLoadIdentity(); // Make sure depth testing and lighting are disabled for 2D rendering until // we are finished rendering in 2D glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_LIGHTING_BIT ); glDisable( GL_DEPTH_TEST ); glDisable( GL_LIGHTING ); // disable the texturing here so crosshair is painted in the correct colors // vtk will reenable texturing every time it is needed glDisable( GL_TEXTURE_1D ); glDisable( GL_TEXTURE_2D ); } /*! \brief Initialize the VtkPropRenderer Enable2DOpenGL() and Disable2DOpenGL() are used to switch between 2D rendering (orthographic projection) and 3D rendering (perspective projection) */ void mitk::VtkPropRenderer::Disable2DOpenGL() { glPopAttrib(); glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glPopMatrix(); } + void mitk::VtkPropRenderer::Update(mitk::DataNode* datatreenode) { if(datatreenode!=NULL) { mitk::Mapper::Pointer mapper = datatreenode->GetMapper(m_MapperID); if(mapper.IsNotNull()) { - Mapper2D* mapper2d=dynamic_cast(mapper.GetPointer()); - if(mapper2d != NULL) + GLMapper* glmapper=dynamic_cast(mapper.GetPointer()); + + if(GetDisplayGeometry()->IsValid()) { - if(GetDisplayGeometry()->IsValid()) + if(glmapper != NULL) { - VtkMapper2D* vtkmapper2d=dynamic_cast(mapper.GetPointer()); - if(vtkmapper2d != NULL) + glmapper->Update(this); + m_VtkMapperPresent=false; + } + else + { + VtkMapper* vtkmapper=dynamic_cast(mapper.GetPointer()); + if(vtkmapper != NULL) { - vtkmapper2d->Update(this); + vtkmapper->Update(this); + vtkmapper->UpdateVtkTransform(this); m_VtkMapperPresent=true; } - else - mapper2d->Update(this); - } - } - else - { - VtkMapper3D* vtkmapper3d=dynamic_cast(mapper.GetPointer()); - if(vtkmapper3d != NULL) - { - vtkmapper3d->Update(this); - vtkmapper3d->UpdateVtkTransform(this); - m_VtkMapperPresent=true; } } } } } void mitk::VtkPropRenderer::Update() { if( m_DataStorage.IsNull() ) return; m_VtkMapperPresent = false; mitk::DataStorage::SetOfObjects::ConstPointer all = m_DataStorage->GetAll(); for (mitk::DataStorage::SetOfObjects::ConstIterator it = all->Begin(); it != all->End(); ++it) Update(it->Value()); Modified(); m_LastUpdateTime = GetMTime(); } /*! \brief This method is called from the two Constructors */ void mitk::VtkPropRenderer::InitRenderer(vtkRenderWindow* renderWindow) { BaseRenderer::InitRenderer(renderWindow); if(renderWindow == NULL) { m_InitNeeded = false; m_ResizeNeeded = false; return; } m_InitNeeded = true; m_ResizeNeeded = true; m_LastUpdateTime = 0; } /*! \brief Resize the OpenGL Window */ void mitk::VtkPropRenderer::Resize(int w, int h) { BaseRenderer::Resize(w, h); m_RenderingManager->RequestUpdate(this->GetRenderWindow()); } void mitk::VtkPropRenderer::InitSize(int w, int h) { m_RenderWindow->SetSize(w,h); Superclass::InitSize(w, h); Modified(); Update(); if(m_VtkRenderer!=NULL) { int w=vtkObject::GetGlobalWarningDisplay(); vtkObject::GlobalWarningDisplayOff(); m_VtkRenderer->ResetCamera(); vtkObject::SetGlobalWarningDisplay(w); } } void mitk::VtkPropRenderer::SetMapperID(const MapperSlotId mapperId) { if(m_MapperID != mapperId) Superclass::SetMapperID(mapperId); // Workaround for GL Displaylist Bug checkState(); } /*! \brief Activates the current renderwindow. */ void mitk::VtkPropRenderer::MakeCurrent() { if(m_RenderWindow!=NULL) m_RenderWindow->MakeCurrent(); } void mitk::VtkPropRenderer::PickWorldPoint(const mitk::Point2D& displayPoint, mitk::Point3D& worldPoint) const { if(m_VtkMapperPresent) { //m_WorldPointPicker->SetTolerance (0.0001); switch ( m_PickingMode ) { case (WorldPointPicking) : { m_WorldPointPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); vtk2itk(m_WorldPointPicker->GetPickPosition(), worldPoint); break; } case (PointPicking) : { // create a new vtkRenderer // give it all necessary information (camera position, etc.) // get all surfaces from datastorage, get actors from them // add all those actors to the new renderer // give this new renderer to pointpicker /* vtkRenderer* pickingRenderer = vtkRenderer::New(); pickingRenderer->SetActiveCamera( ); DataStorage* dataStorage = m_DataStorage; TNodePredicateDataType isSurface; DataStorage::SetOfObjects::ConstPointer allSurfaces = dataStorage->GetSubset( isSurface ); MITK_INFO << "in picking: got " << allSurfaces->size() << " surfaces." << std::endl; for (DataStorage::SetOfObjects::const_iterator iter = allSurfaces->begin(); iter != allSurfaces->end(); ++iter) { const DataNode* currentNode = *iter; VtkMapper3D* baseVtkMapper3D = dynamic_cast( currentNode->GetMapper( BaseRenderer::Standard3D ) ); if ( baseVtkMapper3D ) { vtkActor* actor = dynamic_cast( baseVtkMapper3D->GetViewProp() ); if (actor) { MITK_INFO << "a" << std::flush; pickingRenderer->AddActor( actor ); } } } MITK_INFO << ";" << std::endl; */ m_PointPicker->Pick(displayPoint[0], displayPoint[1], 0, m_VtkRenderer); vtk2itk(m_PointPicker->GetPickPosition(), worldPoint); break; } } } else { Superclass::PickWorldPoint(displayPoint, worldPoint); } } mitk::DataNode * mitk::VtkPropRenderer::PickObject( const Point2D &displayPosition, Point3D &worldPosition ) const { if ( m_VtkMapperPresent ) { m_CellPicker->InitializePickList(); // Iterate over all DataStorage objects to determine all vtkProps intended // for picking DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for ( DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); it != allObjects->End(); ++it ) { DataNode *node = it->Value(); if ( node == NULL ) continue; bool pickable = false; node->GetBoolProperty( "pickable", pickable ); if ( !pickable ) continue; - VtkMapper3D *mapper = dynamic_cast< VtkMapper3D * > - ( node->GetMapper( m_MapperID ) ); + VtkMapper *mapper = dynamic_cast < VtkMapper * > ( node->GetMapper( m_MapperID ) ); if ( mapper == NULL ) continue; vtkProp *prop = mapper->GetVtkProp( (mitk::BaseRenderer *)this ); if ( prop == NULL ) continue; m_CellPicker->AddPickList( prop ); } // Do the picking and retrieve the picked vtkProp (if any) m_CellPicker->PickFromListOn(); m_CellPicker->Pick( displayPosition[0], displayPosition[1], 0.0, m_VtkRenderer ); m_CellPicker->PickFromListOff(); vtk2itk( m_CellPicker->GetPickPosition(), worldPosition ); vtkProp *prop = m_CellPicker->GetViewProp(); if ( prop == NULL ) { return NULL; } // Iterate over all DataStorage objects to determine if the retrieved // vtkProp is owned by any associated mapper. for ( DataStorage::SetOfObjects::ConstIterator it = allObjects->Begin(); it != allObjects->End(); ++it) { DataNode::Pointer node = it->Value(); if ( node.IsNull() ) continue; - mitk::Mapper::Pointer mapper = node->GetMapper( m_MapperID ); - if ( mapper.IsNull() ) + mitk::Mapper * mapper = node->GetMapper( m_MapperID ); + if ( mapper == NULL) continue; - if ( mapper->HasVtkProp( prop, const_cast< mitk::VtkPropRenderer * >( this ) ) ) - { - return node; + mitk::VtkMapper * vtkmapper = dynamic_cast< VtkMapper * >(mapper); + + if(vtkmapper){ + //if vtk-based, then ... + if ( vtkmapper->HasVtkProp( prop, const_cast< mitk::VtkPropRenderer * >( this ) ) ) + { + return node; + } } } return NULL; } else { return Superclass::PickObject( displayPosition, worldPosition ); } }; /*! \brief Writes some 2D text as overlay. Function returns an unique int Text_ID for each call, which can be used via the GetTextLabelProperty(int text_id) function in order to get a vtkTextProperty. This property enables the setup of font, font size, etc. */ int mitk::VtkPropRenderer::WriteSimpleText(std::string text, double posX, double posY, double color1, double color2, double color3, float opacity) { if(text.size() > 0) { vtkTextActor* textActor = vtkTextActor::New(); textActor->SetPosition(posX,posY); textActor->SetInput(text.c_str()); textActor->GetTextProperty()->SetColor(color1, color2, color3); //TODO: Read color from node property textActor->GetTextProperty()->SetOpacity( opacity ); int text_id = m_TextCollection.size(); m_TextCollection.insert(TextMapType::value_type(text_id,textActor)); return text_id; } return -1; } /*! \brief Can be used in order to get a vtkTextProperty for a specific text_id. This property enables the setup of font, font size, etc. */ vtkTextProperty* mitk::VtkPropRenderer::GetTextLabelProperty(int text_id) { return this->m_TextCollection[text_id]->GetTextProperty(); } void mitk::VtkPropRenderer::InitPathTraversal() { if (m_DataStorage.IsNotNull()) { m_PickingObjects = m_DataStorage->GetAll(); m_PickingObjectsIterator = m_PickingObjects->begin(); } } vtkAssemblyPath* mitk::VtkPropRenderer::GetNextPath() { if (m_DataStorage.IsNull() ) { return NULL; } if ( m_PickingObjectsIterator == m_PickingObjects->end() ) { return NULL; } vtkAssemblyPath* returnPath = vtkAssemblyPath::New(); //returnPath->Register(NULL); bool success = false; while (!success) { // loop until AddNode can be called successfully const DataNode* node = *m_PickingObjectsIterator; if (node) { Mapper* mapper = node->GetMapper( BaseRenderer::Standard3D ); if (mapper) { - VtkMapper3D* vtkmapper = dynamic_cast( mapper ); + VtkMapper* vtkmapper = dynamic_cast( mapper ); if (vtkmapper) { vtkProp* prop = vtkmapper->GetVtkProp(this); if ( prop && prop->GetVisibility() ) { // add to assembly path returnPath->AddNode( prop, prop->GetMatrix() ); success = true; } } } } ++m_PickingObjectsIterator; if ( m_PickingObjectsIterator == m_PickingObjects->end() ) break; } if ( success ) { return returnPath; } else { return NULL; } } void mitk::VtkPropRenderer::ReleaseGraphicsResources(vtkWindow *renWin) { if( m_DataStorage.IsNull() ) return; DataStorage::SetOfObjects::ConstPointer allObjects = m_DataStorage->GetAll(); for (DataStorage::SetOfObjects::const_iterator iter = allObjects->begin(); iter != allObjects->end(); ++iter) { DataNode::Pointer node = *iter; if ( node.IsNull() ) continue; - Mapper::Pointer mapper = node->GetMapper(m_MapperID); - if(mapper.IsNotNull()) - mapper->ReleaseGraphicsResources(renWin); - } + Mapper * mapper = node->GetMapper(m_MapperID); + + if (mapper) + { + VtkMapper* vtkmapper = dynamic_cast( mapper ); + + if(vtkmapper) + vtkmapper->ReleaseGraphicsResources(renWin); + } + } } const vtkWorldPointPicker *mitk::VtkPropRenderer::GetWorldPointPicker() const { return m_WorldPointPicker; } const vtkPointPicker *mitk::VtkPropRenderer::GetPointPicker() const { return m_PointPicker; } const vtkCellPicker *mitk::VtkPropRenderer::GetCellPicker() const { return m_CellPicker; } mitk::VtkPropRenderer::MappersMapType mitk::VtkPropRenderer::GetMappersMap() const { return m_MappersMap; } // Workaround for GL Displaylist bug static int glWorkAroundGlobalCount = 0; bool mitk::VtkPropRenderer::useImmediateModeRendering() { return glWorkAroundGlobalCount>1; } void mitk::VtkPropRenderer::checkState() { if (m_MapperID == Standard3D) { if (!didCount) { didCount = true; glWorkAroundGlobalCount++; if (glWorkAroundGlobalCount == 2) { MITK_INFO << "Multiple 3D Renderwindows active...: turning Immediate Rendering ON for legacy mappers"; // vtkMapper::GlobalImmediateModeRenderingOn(); } //MITK_INFO << "GLOBAL 3D INCREASE " << glWorkAroundGlobalCount << "\n"; } } else { if(didCount) { didCount=false; glWorkAroundGlobalCount--; if(glWorkAroundGlobalCount==1) { MITK_INFO << "Single 3D Renderwindow active...: turning Immediate Rendering OFF for legacy mappers"; // vtkMapper::GlobalImmediateModeRenderingOff(); } //MITK_INFO << "GLOBAL 3D DECREASE " << glWorkAroundGlobalCount << "\n"; } } } //### Contains all methods which are neceassry before each VTK Render() call void mitk::VtkPropRenderer::PrepareRender() { if ( this->GetMapperID() != m_CameraInitializedForMapperID ) { Initialize2DvtkCamera(); //Set parallel projection etc. } AdjustCameraToScene(); //Prepare camera for 2D render windows } bool mitk::VtkPropRenderer::Initialize2DvtkCamera() { if ( this->GetMapperID() == Standard3D ) { //activate parallel projection for 2D this->GetVtkRenderer()->GetActiveCamera()->SetParallelProjection(false); this->GetRenderWindow()->GetInteractor()->SetInteractorStyle( vtkInteractorStyleTrackballCamera::New() ); m_CameraInitializedForMapperID = Standard3D; } else if( this->GetMapperID() == Standard2D) { //activate parallel projection for 2D this->GetVtkRenderer()->GetActiveCamera()->SetParallelProjection(true); //turn the light out in the scene in order to render correct grey values. //TODO Implement a property for light in the 2D render windows (in another method) this->GetVtkRenderer()->RemoveAllLights(); this->GetRenderWindow()->GetInteractor()->SetInteractorStyle( mitkVtkInteractorStyle::New() ); m_CameraInitializedForMapperID = Standard2D; } return true; } void mitk::VtkPropRenderer::AdjustCameraToScene(){ if(this->GetMapperID() == Standard2D) { const mitk::DisplayGeometry* displayGeometry = this->GetDisplayGeometry(); double objectHeightInMM = this->GetCurrentWorldGeometry2D()->GetExtentInMM(1);//the height of the current object slice in mm double displayHeightInMM = displayGeometry->GetSizeInMM()[1]; //the display height in mm (gets smaller when you zoom in) double zoomFactor = objectHeightInMM/displayHeightInMM; //displayGeometry->GetScaleFactorMMPerDisplayUnit() //determine how much of the object can be displayed Vector2D displayGeometryOriginInMM = displayGeometry->GetOriginInMM(); //top left of the render window (Origin) Vector2D displayGeometryCenterInMM = displayGeometryOriginInMM + displayGeometry->GetSizeInMM()*0.5; //center of the render window: (Origin + Size/2) //Scale the rendered object: //The image is scaled by a single factor, because in an orthographic projection sizes //are preserved (so you cannot scale X and Y axis with different parameters). The //parameter sets the size of the total display-volume. If you set this to the image //height, the image plus a border with the size of the image will be rendered. //Therefore, the size is imageHeightInMM / 2. this->GetVtkRenderer()->GetActiveCamera()->SetParallelScale(objectHeightInMM*0.5 ); //zooming with the factor calculated by dividing displayHeight through imegeHeight. The factor is inverse, because the VTK zoom method is working inversely. this->GetVtkRenderer()->GetActiveCamera()->Zoom(zoomFactor); //the center of the view-plane double viewPlaneCenter[3]; viewPlaneCenter[0] = displayGeometryCenterInMM[0]; viewPlaneCenter[1] = displayGeometryCenterInMM[1]; viewPlaneCenter[2] = 0.0; //the view-plane is located in the XY-plane with Z=0.0 //define which direction is "up" for the ciamera (like default for vtk (0.0, 1.0, 0.0) double cameraUp[3]; cameraUp[0] = 0.0; cameraUp[1] = 1.0; cameraUp[2] = 0.0; //the position of the camera (center[0], center[1], 900000) double cameraPosition[3]; cameraPosition[0] = viewPlaneCenter[0]; cameraPosition[1] = viewPlaneCenter[1]; cameraPosition[2] = 900000.0; //Reason for 900000: VTK seems to calculate the clipping planes wrong for small values. See VTK bug (id #7823) in VTK bugtracker. //set the camera corresponding to the textured plane vtkSmartPointer camera = this->GetVtkRenderer()->GetActiveCamera(); if (camera) { camera->SetPosition( cameraPosition ); //set the camera position on the textured plane normal (in our case this is the view plane normal) camera->SetFocalPoint( viewPlaneCenter ); //set the focal point to the center of the textured plane camera->SetViewUp( cameraUp ); //set the view-up for the camera // double distance = sqrt((cameraPosition[2]-viewPlaneCenter[2])*(cameraPosition[2]-viewPlaneCenter[2])); // camera->SetClippingRange(distance-50, distance+50); //Reason for huge range: VTK seems to calculate the clipping planes wrong for small values. See VTK bug (id #7823) in VTK bugtracker. camera->SetClippingRange(0.1, 1000000); //Reason for huge range: VTK seems to calculate the clipping planes wrong for small values. See VTK bug (id #7823) in VTK bugtracker. } const PlaneGeometry *planeGeometry = dynamic_cast< const PlaneGeometry * >( this->GetCurrentWorldGeometry2D() ); if ( planeGeometry != NULL ) { //Transform the camera to the current position (transveral, coronal and saggital plane). //This is necessary, because the SetUserTransform() method does not manipulate the vtkCamera. //(Without not all three planes would be visible). vtkSmartPointer trans = vtkSmartPointer::New(); vtkSmartPointer matrix = vtkSmartPointer::New(); Point3D origin; Vector3D right, bottom, normal; origin = planeGeometry->GetOrigin(); right = planeGeometry->GetAxisVector( 0 ); // right = Extent of Image in mm (worldspace) bottom = planeGeometry->GetAxisVector( 1 ); normal = planeGeometry->GetNormal(); right.Normalize(); bottom.Normalize(); normal.Normalize(); matrix->SetElement(0, 0, right[0]); matrix->SetElement(1, 0, right[1]); matrix->SetElement(2, 0, right[2]); matrix->SetElement(0, 1, bottom[0]); matrix->SetElement(1, 1, bottom[1]); matrix->SetElement(2, 1, bottom[2]); matrix->SetElement(0, 2, normal[0]); matrix->SetElement(1, 2, normal[1]); matrix->SetElement(2, 2, normal[2]); matrix->SetElement(0, 3, origin[0]); matrix->SetElement(1, 3, origin[1]); matrix->SetElement(2, 3, origin[2]); matrix->SetElement(3, 0, 0.0); matrix->SetElement(3, 1, 0.0); matrix->SetElement(3, 2, 0.0); matrix->SetElement(3, 3, 1.0); trans->SetMatrix(matrix); //Transform the camera to the current position (transveral, coronal and saggital plane). this->GetVtkRenderer()->GetActiveCamera()->ApplyTransform(trans); } } } diff --git a/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp b/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp index f63654f949..d53739f41a 100644 --- a/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp +++ b/Core/Code/Rendering/vtkMitkLevelWindowFilter.cpp @@ -1,493 +1,597 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "vtkMitkLevelWindowFilter.h" #include #include #include +#include //used for acos etc. #include //used for PI #include #include static const double PI = itk::Math::pi; vtkMitkLevelWindowFilter::vtkMitkLevelWindowFilter():m_MinOpacity(0.0),m_MaxOpacity(255.0) { //MITK_INFO << "mitk level/window filter uses " << GetNumberOfThreads() << " thread(s)"; } vtkMitkLevelWindowFilter::~vtkMitkLevelWindowFilter() { } unsigned long int vtkMitkLevelWindowFilter::GetMTime() { unsigned long mTime=this->vtkObject::GetMTime(); unsigned long time; if ( this->m_LookupTable != NULL ) { time = this->m_LookupTable->GetMTime(); mTime = ( time > mTime ? time : mTime ); } return mTime; } void vtkMitkLevelWindowFilter::SetLookupTable(vtkScalarsToColors *lookupTable) { if (m_LookupTable != lookupTable) { m_LookupTable = lookupTable; this->Modified(); } } vtkScalarsToColors* vtkMitkLevelWindowFilter::GetLookupTable() { return m_LookupTable; } //This code was copied from the iil. The template works only for float and double. //Internal method which should never be used anywhere else and should not be in th header. // Convert color pixels from (R,G,B) to (H,S,I). // Reference: "Digital Image Processing, 2nd. edition", R. Gonzalez and R. Woods. Prentice Hall, 2002. template void RGBtoHSI(T* RGB, T* HSI) { T R = RGB[0], G = RGB[1], B = RGB[2], nR = (R<0?0:(R>255?255:R))/255, nG = (G<0?0:(G>255?255:G))/255, nB = (B<0?0:(B>255?255:B))/255, m = nR0) H = (nB<=nG)?theta:360-theta; if (sum>0) S = 1 - 3/sum*m; I = sum/3; HSI[0] = (T)H; HSI[1] = (T)S; HSI[2] = (T)I; } //This code was copied from the iil. The template works only for float and double. //Internal method which should never be used anywhere else and should not be in th header. // Convert color pixels from (H,S,I) to (R,G,B). template void HSItoRGB(T* HSI, T* RGB) { T H = (T)HSI[0], S = (T)HSI[1], I = (T)HSI[2], a = I*(1-S), R = 0, G = 0, B = 0; if (H<120) { B = a; R = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); G = 3*I-(R+B); } else if (H<240) { H-=120; R = a; G = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); B = 3*I-(R+G); } else { H-=240; G = a; B = (T)(I*(1+S*std::cos(H*PI/180)/std::cos((60-H)*PI/180))); R = 3*I-(G+B); } R*=255; G*=255; B*=255; RGB[0] = (T)(R<0?0:(R>255?255:R)); RGB[1] = (T)(G<0?0:(G>255?255:G)); RGB[2] = (T)(B<0?0:(B>255?255:B)); } //Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnRGBA(vtkMitkLevelWindowFilter* self, vtkImageData* inData, vtkImageData* outData, int outExt[6], vtkFloatingPointType* clippingBounds, T*) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkLookupTable* lookupTable; const int maxC = inData->GetNumberOfScalarComponents(); double tableRange[2]; lookupTable = dynamic_cast(self->GetLookupTable()); lookupTable->GetTableRange(tableRange); //parameters for RGB level window double scale = (tableRange[1] -tableRange[0] > 0 ? 255.0 / (tableRange[1] - tableRange[0]) : 0.0); double bias = tableRange[0] * scale; //parameters for opaque level window double scaleOpac = (self->GetMaxOpacity() -self->GetMinOpacity() > 0 ? 255.0 / (self->GetMaxOpacity() - self->GetMinOpacity()) : 0.0); double biasOpac = self->GetMinOpacity() * scaleOpac; int y = outExt[2]; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { T* inputSI = inputIt.BeginSpan(); T* outputSI = outputIt.BeginSpan(); T* outputSIEnd = outputIt.EndSpan(); if( y >= clippingBounds[2] && y < clippingBounds[3] ) { int x = outExt[0]; while (outputSI != outputSIEnd) { if ( x >= clippingBounds[0] && x < clippingBounds[1]) { double rgb[3], alpha, hsi[3]; // level/window mechanism for intensity in HSI space rgb[0] = static_cast(*inputSI); inputSI++; rgb[1] = static_cast(*inputSI); inputSI++; rgb[2] = static_cast(*inputSI); inputSI++; RGBtoHSI(rgb,hsi); hsi[2] = hsi[2] * 255.0 * scale - bias; hsi[2] = (hsi[2] > 255.0 ? 255 : (hsi[2] < 0.0 ? 0 : hsi[2])); hsi[2] /= 255.0; HSItoRGB(hsi,rgb); *outputSI = static_cast(rgb[0]); outputSI++; *outputSI = static_cast(rgb[1]); outputSI++; *outputSI = static_cast(rgb[2]); outputSI++; unsigned char finalAlpha = 255; //RGBA case if(maxC >= 4) { // level/window mechanism for opacity alpha = static_cast(*inputSI); inputSI++; alpha = alpha * scaleOpac - biasOpac; if(alpha > 255.0) { alpha = 255.0; } else if(alpha < 0.0) { alpha = 0.0; } finalAlpha = static_cast(alpha); for( int c = 4; c < maxC; c++ ) inputSI++; } *outputSI = static_cast(finalAlpha); outputSI++; } else { inputSI+=maxC; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; } x++; } } else { while (outputSI != outputSIEnd) { *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; *outputSI = 0; outputSI++; } } inputIt.NextSpan(); outputIt.NextSpan(); y++; } } //Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnScalarsFast(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); double tableRange[2]; // access vtkLookupTable vtkLookupTable* lookupTable = dynamic_cast(self->GetLookupTable()); lookupTable->GetTableRange(tableRange); // access elements of the vtkLookupTable int * realLookupTable = reinterpret_cast(lookupTable->GetTable()->GetPointer(0)); int maxIndex = lookupTable->GetNumberOfColors() - 1; float scale = (tableRange[1] -tableRange[0] > 0 ? (maxIndex + 1) / (tableRange[1] - tableRange[0]) : 0.0); // ensuring that starting point is zero float bias = - tableRange[0] * scale; // due to later conversion to int for rounding bias += 0.5f; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { unsigned char* outputSI = outputIt.BeginSpan(); unsigned char* outputSIEnd = outputIt.EndSpan(); T* inputSI = inputIt.BeginSpan(); while (outputSI != outputSIEnd) { // map to an index int idx = static_cast( *inputSI * scale + bias ); if (idx < 0) idx = 0; else if (idx > maxIndex) idx = maxIndex; * reinterpret_cast(outputSI) = realLookupTable[idx]; inputSI++; outputSI+=4; } inputIt.NextSpan(); outputIt.NextSpan(); } } //Internal method which should never be used anywhere else and should not be in th header. //---------------------------------------------------------------------------- // This templated function executes the filter for any type of data. template void vtkApplyLookupTableOnScalars(vtkMitkLevelWindowFilter *self, vtkImageData *inData, vtkImageData *outData, int outExt[6], vtkFloatingPointType* clippingBounds, T *) { vtkImageIterator inputIt(inData, outExt); vtkImageIterator outputIt(outData, outExt); vtkScalarsToColors* lookupTable = self->GetLookupTable(); int y = outExt[2]; // Loop through ouput pixels while (!outputIt.IsAtEnd()) { unsigned char* outputSI = outputIt.BeginSpan(); unsigned char* outputSIEnd = outputIt.EndSpan(); // do we iterate over the inner vertical clipping bounds if( y >= clippingBounds[2] && y < clippingBounds[3] ) { T* inputSI = inputIt.BeginSpan(); int x= outExt[0]; while (outputSI != outputSIEnd) { // is this pixel within horizontal clipping bounds if ( x >= clippingBounds[0] && x < clippingBounds[1]) { // fetching original value double grayValue = static_cast(*inputSI); // applying lookuptable - copy the 4 (RGBA) chars as a single int *reinterpret_cast(outputSI) = *reinterpret_cast(lookupTable->MapValue( grayValue )); } else { // outer horizontal clipping bounds - write a transparent RGBA pixel as a single int *reinterpret_cast(outputSI) = 0; } inputSI++; outputSI+=4; x++; } } else { // outer vertical clipping bounds - write a transparent RGBA line as ints while (outputSI != outputSIEnd) { *reinterpret_cast(outputSI) = 0; outputSI+=4; } } inputIt.NextSpan(); outputIt.NextSpan(); y++; } } + +//Internal method which should never be used anywhere else and should not be in th header. +//---------------------------------------------------------------------------- +// This templated function executes the filter for any type of data. +template +void vtkApplyLookupTableOnScalarsCTF(vtkMitkLevelWindowFilter *self, + vtkImageData *inData, + vtkImageData *outData, + int outExt[6], + vtkFloatingPointType* clippingBounds, + T *) +{ + vtkImageIterator inputIt(inData, outExt); + vtkImageIterator outputIt(outData, outExt); + vtkColorTransferFunction* lookupTable = dynamic_cast(self->GetLookupTable()); + + int y = outExt[2]; + + // Loop through ouput pixels + while (!outputIt.IsAtEnd()) + { + unsigned char* outputSI = outputIt.BeginSpan(); + unsigned char* outputSIEnd = outputIt.EndSpan(); + + // do we iterate over the inner vertical clipping bounds + if( y >= clippingBounds[2] && y < clippingBounds[3] ) + { + T* inputSI = inputIt.BeginSpan(); + + int x= outExt[0]; + + while (outputSI != outputSIEnd) + { + // is this pixel within horizontal clipping bounds + if ( x >= clippingBounds[0] && x < clippingBounds[1]) + { + // fetching original value + double grayValue = static_cast(*inputSI); + + // applying directly colortransferfunction + // because vtkColorTransferFunction::MapValue is not threadsafe + double rgb[3]; + lookupTable->GetColor( grayValue, rgb ); + + outputSI[0] = static_cast(255.0*rgb[0] + 0.5); + outputSI[1] = static_cast(255.0*rgb[1] + 0.5); + outputSI[2] = static_cast(255.0*rgb[2] + 0.5); + outputSI[3] = 255; + } + else + { + // outer horizontal clipping bounds - write a transparent RGBA pixel as a single int + *reinterpret_cast(outputSI) = 0; + } + + inputSI++; + outputSI+=4; + x++; + } + + } + else + { + // outer vertical clipping bounds - write a transparent RGBA line as ints + while (outputSI != outputSIEnd) + { + *reinterpret_cast(outputSI) = 0; + outputSI+=4; + } + } + + inputIt.NextSpan(); + outputIt.NextSpan(); + y++; + } +} + + + void vtkMitkLevelWindowFilter::ExecuteInformation() { vtkImageData *input = this->GetInput(); vtkImageData *output = this->GetOutput(); if (!input) { vtkErrorMacro(<< "Input not set."); return; } output->CopyTypeSpecificInformation( input ); // TODO make output RGBA output->SetScalarTypeToUnsignedChar(); output->SetNumberOfScalarComponents(4); int extent[6]; input->GetWholeExtent(extent); output->SetExtent(extent); output->SetWholeExtent(extent); output->SetUpdateExtent(extent); output->AllocateScalars(); } //Method to run the filter in different threads. void vtkMitkLevelWindowFilter::ThreadedExecute(vtkImageData *inData, vtkImageData *outData, int extent[6], int /*id*/) { if(inData->GetNumberOfScalarComponents() > 2) { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnRGBA( this, inData, outData, extent, m_ClippingBounds, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } } else { bool dontClip = extent[2] >= m_ClippingBounds[2] && extent[3] <= m_ClippingBounds[3] && extent[0] >= m_ClippingBounds[0] && extent[1] <= m_ClippingBounds[1]; + if(this->GetLookupTable()) + this->GetLookupTable()->Build(); + vtkLookupTable *vlt = dynamic_cast(this->GetLookupTable()); + vtkColorTransferFunction *ctf = dynamic_cast(this->GetLookupTable()); bool linearLookupTable = vlt && vlt->GetScale() == VTK_SCALE_LINEAR; bool useFast = dontClip && linearLookupTable; - if(useFast) + if(ctf) + { + switch (inData->GetScalarType()) + { + vtkTemplateMacro( + vtkApplyLookupTableOnScalarsCTF( this, + inData, + outData, + extent, + m_ClippingBounds, + static_cast(0))); + default: + vtkErrorMacro(<< "Execute: Unknown ScalarType"); + return; + } + } + else if(useFast) + { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnScalarsFast( this, inData, outData, extent, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } + } else + { switch (inData->GetScalarType()) { vtkTemplateMacro( vtkApplyLookupTableOnScalars( this, inData, outData, extent, m_ClippingBounds, static_cast(0))); default: vtkErrorMacro(<< "Execute: Unknown ScalarType"); return; } + } } } void vtkMitkLevelWindowFilter::ExecuteInformation( vtkImageData *vtkNotUsed(inData), vtkImageData *vtkNotUsed(outData)) { } void vtkMitkLevelWindowFilter::SetMinOpacity(double minOpacity) { m_MinOpacity = minOpacity; } inline double vtkMitkLevelWindowFilter::GetMinOpacity() const { return m_MinOpacity; } void vtkMitkLevelWindowFilter::SetMaxOpacity(double maxOpacity) { m_MaxOpacity = maxOpacity; } inline double vtkMitkLevelWindowFilter::GetMaxOpacity() const { return m_MaxOpacity; } void vtkMitkLevelWindowFilter::SetClippingBounds(vtkFloatingPointType* bounds) // TODO does vtkFloatingPointType[4] work?? { for (unsigned int i = 0 ; i < 4; ++i) m_ClippingBounds[i] = bounds[i]; } diff --git a/Core/Code/Rendering/vtkMitkRenderProp.cpp b/Core/Code/Rendering/vtkMitkRenderProp.cpp index f1839cf303..59d4c6bf9d 100644 --- a/Core/Code/Rendering/vtkMitkRenderProp.cpp +++ b/Core/Code/Rendering/vtkMitkRenderProp.cpp @@ -1,125 +1,107 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "vtkMitkRenderProp.h" #include #include #include -#include "mitkVtkMapper3D.h" -#include "mitkVtkMapper2D.h" +#include "mitkVtkMapper.h" +#include "mitkGLMapper.h" vtkStandardNewMacro(vtkMitkRenderProp); vtkMitkRenderProp::vtkMitkRenderProp() { } vtkMitkRenderProp::~vtkMitkRenderProp() { } double *vtkMitkRenderProp::GetBounds() { return const_cast(m_VtkPropRenderer->GetBounds()); } void vtkMitkRenderProp::SetPropRenderer(mitk::VtkPropRenderer::Pointer propRenderer) { this->m_VtkPropRenderer = propRenderer; } int vtkMitkRenderProp::RenderOpaqueGeometry(vtkViewport* /*viewport*/) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Opaque); } int vtkMitkRenderProp::RenderOverlay(vtkViewport* /*viewport*/) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Overlay); } void vtkMitkRenderProp::ReleaseGraphicsResources(vtkWindow* window) { m_VtkPropRenderer->ReleaseGraphicsResources(window); } void vtkMitkRenderProp::InitPathTraversal() { m_VtkPropRenderer->InitPathTraversal(); } vtkAssemblyPath* vtkMitkRenderProp::GetNextPath() { return m_VtkPropRenderer->GetNextPath(); } //BUG (#1551) added method depth peeling int vtkMitkRenderProp::HasTranslucentPolygonalGeometry() { typedef std::map MappersMapType; MappersMapType mappersMap = m_VtkPropRenderer->GetMappersMap(); for(MappersMapType::iterator it = mappersMap.begin(); it != mappersMap.end(); it++) { mitk::Mapper * mapper = (*it).second; - mitk::VtkMapper3D::Pointer vtkMapper3D = dynamic_cast(mapper); - if(vtkMapper3D) - { - // Due to VTK 5.2 bug, we need to initialize the Paths object in vtkPropAssembly - // manually (see issue #8186 committed to VTK's Mantis issue tracker) - // --> VTK bug resolved on 2008-12-01 - vtkPropAssembly *propAssembly = dynamic_cast< vtkPropAssembly * >( - vtkMapper3D->GetVtkProp(m_VtkPropRenderer) ); - if ( propAssembly ) - { - propAssembly->InitPathTraversal(); - } - if (vtkMapper3D->GetVtkProp(m_VtkPropRenderer)->HasTranslucentPolygonalGeometry()==1) - return 1; - } - - //TODO bad solution. - mitk::VtkMapper2D::Pointer vtkMapper2D = dynamic_cast(mapper); - if(vtkMapper2D) + mitk::VtkMapper::Pointer vtkMapper = dynamic_cast(mapper); + if(vtkMapper) { // Due to VTK 5.2 bug, we need to initialize the Paths object in vtkPropAssembly // manually (see issue #8186 committed to VTK's Mantis issue tracker) // --> VTK bug resolved on 2008-12-01 vtkPropAssembly *propAssembly = dynamic_cast< vtkPropAssembly * >( - vtkMapper2D->GetVtkProp(m_VtkPropRenderer) ); + vtkMapper->GetVtkProp(m_VtkPropRenderer) ); if ( propAssembly ) { - propAssembly->InitPathTraversal(); //TODO why is this called here??? + propAssembly->InitPathTraversal(); } - if (vtkMapper2D->GetVtkProp(m_VtkPropRenderer)->HasTranslucentPolygonalGeometry()==1) { + if (vtkMapper->GetVtkProp(m_VtkPropRenderer)->HasTranslucentPolygonalGeometry()==1) return 1; - } } } return 0; } int vtkMitkRenderProp::RenderTranslucentPolygonalGeometry( vtkViewport * ) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Translucent); } int vtkMitkRenderProp::RenderVolumetricGeometry( vtkViewport * ) { return m_VtkPropRenderer->Render(mitk::VtkPropRenderer::Volumetric); } diff --git a/Core/Code/Rendering/vtkMitkRenderProp.h b/Core/Code/Rendering/vtkMitkRenderProp.h index 9be98656c0..4ac689567c 100644 --- a/Core/Code/Rendering/vtkMitkRenderProp.h +++ b/Core/Code/Rendering/vtkMitkRenderProp.h @@ -1,79 +1,75 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef VTKMITKRENDERPROP_H_HEADER_INCLUDED_C1C53723 #define VTKMITKRENDERPROP_H_HEADER_INCLUDED_C1C53723 #include "vtkProp.h" #include "mitkVtkPropRenderer.h" - - /*! \brief vtkMitkRenderProp The MITK rendering process is completely integrated into the VTK rendering pipeline. The vtkMitkRenderProp is a custom vtkProp derived class, which implements the rendering interface between MITK and VTK. It redirects render() calls to the VtkPropRenderer, which is responsible for rendering of the datatreenodes. \sa rendering \ingroup rendering */ class MITK_CORE_EXPORT vtkMitkRenderProp : public vtkProp { public: static vtkMitkRenderProp *New(); vtkTypeMacro(vtkMitkRenderProp,vtkProp); void SetPropRenderer(mitk::VtkPropRenderer::Pointer propRenderer); int RenderOpaqueGeometry(vtkViewport* viewport); int RenderOverlay(vtkViewport* viewport); double *GetBounds(); void ReleaseGraphicsResources(vtkWindow* window); /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ virtual void InitPathTraversal(); /** * \brief Used by vtkPointPicker/vtkPicker. * This will query a list of all objects in MITK and provide every vtk based mapper to the picker. */ virtual vtkAssemblyPath* GetNextPath(); //BUG (#1551) added method for depth peeling support virtual int HasTranslucentPolygonalGeometry(); virtual int RenderTranslucentPolygonalGeometry( vtkViewport *); virtual int RenderVolumetricGeometry( vtkViewport *); protected: vtkMitkRenderProp(); ~vtkMitkRenderProp(); mitk::VtkPropRenderer::Pointer m_VtkPropRenderer; }; #endif /* VTKMITKRENDERPROP_H_HEADER_INCLUDED_C1C53723 */ - - diff --git a/Core/Code/Resources/Interactions/DisplayConfig.xml b/Core/Code/Resources/Interactions/DisplayConfig.xml index 3a402dac02..5e76716816 100644 --- a/Core/Code/Resources/Interactions/DisplayConfig.xml +++ b/Core/Code/Resources/Interactions/DisplayConfig.xml @@ -1,73 +1,73 @@ - + - - + + - - + + - + - + - - + + - - + + - + - + - - + + - - + + - - + + - + - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigMITK.xml b/Core/Code/Resources/Interactions/DisplayConfigMITK.xml index 6f9e94ebea..025b59f5fc 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigMITK.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigMITK.xml @@ -1,43 +1,43 @@ - + - - + + - - + + - + - + - - + + - - + + - + - + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigPACS.xml b/Core/Code/Resources/Interactions/DisplayConfigPACS.xml index 3f1b91e99f..32a58497d0 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigPACS.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigPACS.xml @@ -1,60 +1,60 @@ - + - - + + - - + + - + - + - - + + - - + + - + - + - - + + - - + + - + - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigPACSLevelWindow.xml b/Core/Code/Resources/Interactions/DisplayConfigPACSLevelWindow.xml index 095f574ece..b8604d340f 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigPACSLevelWindow.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigPACSLevelWindow.xml @@ -1,11 +1,11 @@ - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigPACSPan.xml b/Core/Code/Resources/Interactions/DisplayConfigPACSPan.xml index 04a0c04045..35eaa333c5 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigPACSPan.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigPACSPan.xml @@ -1,11 +1,11 @@ - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigPACSScroll.xml b/Core/Code/Resources/Interactions/DisplayConfigPACSScroll.xml index a85aeef7e9..a3a5e3cf9c 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigPACSScroll.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigPACSScroll.xml @@ -1,13 +1,13 @@ - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/DisplayConfigPACSZoom.xml b/Core/Code/Resources/Interactions/DisplayConfigPACSZoom.xml index 17bc572c40..c5defb7806 100644 --- a/Core/Code/Resources/Interactions/DisplayConfigPACSZoom.xml +++ b/Core/Code/Resources/Interactions/DisplayConfigPACSZoom.xml @@ -1,11 +1,11 @@ - + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/PointSetConfig.xml b/Core/Code/Resources/Interactions/PointSetConfig.xml index dfd8c206a2..f38f80b075 100644 --- a/Core/Code/Resources/Interactions/PointSetConfig.xml +++ b/Core/Code/Resources/Interactions/PointSetConfig.xml @@ -1,40 +1,40 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/Tests/StatemachineConfigTest.xml b/Core/Code/Resources/Interactions/Tests/StatemachineConfigTest.xml index a87fec05e8..b0e0095457 100644 --- a/Core/Code/Resources/Interactions/Tests/StatemachineConfigTest.xml +++ b/Core/Code/Resources/Interactions/Tests/StatemachineConfigTest.xml @@ -1,19 +1,19 @@ - + - - + + - - + + - - + + - + diff --git a/Core/Code/Resources/Interactions/Tests/globalConfig.xml b/Core/Code/Resources/Interactions/Tests/globalConfig.xml index 6d7ef6fd3f..34d543270c 100644 --- a/Core/Code/Resources/Interactions/Tests/globalConfig.xml +++ b/Core/Code/Resources/Interactions/Tests/globalConfig.xml @@ -1,70 +1,70 @@ - + - - + + - - + + - - + + - + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - + - + - - + + - + - + - - + + - + diff --git a/Core/Code/Resources/Interactions/globalConfig.xml b/Core/Code/Resources/Interactions/globalConfig.xml index 6d7ef6fd3f..34d543270c 100644 --- a/Core/Code/Resources/Interactions/globalConfig.xml +++ b/Core/Code/Resources/Interactions/globalConfig.xml @@ -1,70 +1,70 @@ - + - - + + - - + + - - + + - + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - + - + - - + + - + - + - - + + - + diff --git a/Core/Code/Testing/Testing/Temporary/CTestCostData.txt b/Core/Code/Testing/Testing/Temporary/CTestCostData.txt deleted file mode 100644 index ed97d539c0..0000000000 --- a/Core/Code/Testing/Testing/Temporary/CTestCostData.txt +++ /dev/null @@ -1 +0,0 @@ ---- diff --git a/Core/Code/Testing/Testing/Temporary/LastTest.log b/Core/Code/Testing/Testing/Temporary/LastTest.log deleted file mode 100644 index 83c8c4ffeb..0000000000 --- a/Core/Code/Testing/Testing/Temporary/LastTest.log +++ /dev/null @@ -1,3 +0,0 @@ -Start testing: Nov 23 15:04 CET ----------------------------------------------------------- -End testing: Nov 23 15:04 CET diff --git a/Core/Code/Testing/files.cmake b/Core/Code/Testing/files.cmake index a11495c505..ba5b80727d 100644 --- a/Core/Code/Testing/files.cmake +++ b/Core/Code/Testing/files.cmake @@ -1,128 +1,128 @@ # tests with no extra command line parameter set(MODULE_TESTS mitkAccessByItkTest.cpp mitkCoreObjectFactoryTest.cpp mitkMaterialTest.cpp mitkActionTest.cpp mitkDispatcherTest.cpp mitkEnumerationPropertyTest.cpp mitkEventTest.cpp - mitkEventConfigTest.cpp + #mitkEventConfigTest.cpp ## needs to be re-written, test indirect since EventConfig is no longer exported as interface Bug 14529 mitkFocusManagerTest.cpp mitkGenericPropertyTest.cpp mitkGeometry3DTest.cpp mitkGeometryDataToSurfaceFilterTest.cpp mitkGlobalInteractionTest.cpp mitkImageDataItemTest.cpp #mitkImageMapper2DTest.cpp mitkImageGeneratorTest.cpp mitkBaseDataTest.cpp #mitkImageToItkTest.cpp mitkInstantiateAccessFunctionTest.cpp mitkInteractorTest.cpp mitkInteractionEventTest.cpp mitkITKThreadingTest.cpp mitkLevelWindowTest.cpp mitkMessageTest.cpp #mitkPipelineSmartPointerCorrectnessTest.cpp mitkPixelTypeTest.cpp mitkPlaneGeometryTest.cpp mitkPointSetFileIOTest.cpp mitkPointSetTest.cpp mitkPointSetWriterTest.cpp mitkPointSetReaderTest.cpp mitkPointSetInteractorTest.cpp mitkPropertyTest.cpp mitkPropertyListTest.cpp #mitkRegistrationBaseTest.cpp #mitkSegmentationInterpolationTest.cpp mitkSlicedGeometry3DTest.cpp mitkSliceNavigationControllerTest.cpp mitkStateMachineTest.cpp - mitkStateMachineContainerTest.cpp + ##mitkStateMachineContainerTest.cpp ## rewrite test, indirect since no longer exported Bug 14529 mitkStateTest.cpp mitkSurfaceTest.cpp mitkSurfaceToSurfaceFilterTest.cpp mitkTimeSlicedGeometryTest.cpp mitkTransitionTest.cpp mitkUndoControllerTest.cpp mitkVtkWidgetRenderingTest.cpp mitkVerboseLimitedLinearUndoTest.cpp mitkWeakPointerTest.cpp mitkTransferFunctionTest.cpp #mitkAbstractTransformGeometryTest.cpp mitkStepperTest.cpp itkTotalVariationDenoisingImageFilterTest.cpp mitkRenderingManagerTest.cpp vtkMitkThickSlicesFilterTest.cpp mitkNodePredicateSourceTest.cpp mitkVectorTest.cpp mitkClippedSurfaceBoundsCalculatorTest.cpp #QmitkRenderingTestHelper.cpp mitkExceptionTest.cpp mitkExtractSliceFilterTest.cpp mitkLogTest.cpp mitkImageDimensionConverterTest.cpp mitkLoggingAdapterTest.cpp mitkUIDGeneratorTest.cpp ) # test with image filename as an extra command line parameter set(MODULE_IMAGE_TESTS mitkPlanePositionManagerTest.cpp mitkSurfaceVtkWriterTest.cpp #mitkImageSliceSelectorTest.cpp mitkImageTimeSelectorTest.cpp # mitkVtkPropRendererTest.cpp mitkDataNodeFactoryTest.cpp #mitkSTLFileReaderTest.cpp mitkImageAccessorTest.cpp ) # list of images for which the tests are run set(MODULE_TESTIMAGES # Pic-Factory no more available in Core, test images now in .nrrd format US4DCyl.nrrd Pic3D.nrrd Pic2DplusT.nrrd BallBinary30x30x30.nrrd binary.stl ball.stl ) set(MODULE_CUSTOM_TESTS #mitkLabeledImageToSurfaceFilterTest.cpp #mitkExternalToolsTest.cpp mitkDataStorageTest.cpp mitkDataNodeTest.cpp mitkDicomSeriesReaderTest.cpp mitkDICOMLocaleTest.cpp mitkEventMapperTest.cpp mitkNodeDependentPointSetInteractorTest.cpp mitkStateMachineFactoryTest.cpp mitkPointSetLocaleTest.cpp mitkImageTest.cpp mitkImageWriterTest.cpp mitkImageVtkMapper2DTest.cpp mitkImageVtkMapper2DLevelWindowTest.cpp mitkImageVtkMapper2DOpacityTest.cpp mitkImageVtkMapper2DColorTest.cpp mitkImageVtkMapper2DSwivelTest.cpp mitkIOUtilTest.cpp mitkSurfaceVtkMapper3DTest mitkSurfaceVtkMapper3DTexturedSphereTest.cpp mitkVolumeCalculatorTest.cpp mitkLevelWindowManagerTest.cpp ) # Create an artificial module initializing class for # the usServiceListenerTest.cpp usFunctionGenerateModuleInit(testdriver_init_file NAME ${MODULE_NAME}TestDriver DEPENDS "Mitk" VERSION "0.1.0" EXECUTABLE ) -set(TEST_CPP_FILES ${testdriver_init_file} mitkRenderingTestHelper.cpp) +set(TEST_CPP_FILES ${testdriver_init_file}) diff --git a/Core/Code/Testing/mitkDispatcherTest.cpp b/Core/Code/Testing/mitkDispatcherTest.cpp index 4b1069543a..7f9f49cc66 100644 --- a/Core/Code/Testing/mitkDispatcherTest.cpp +++ b/Core/Code/Testing/mitkDispatcherTest.cpp @@ -1,119 +1,122 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkStandaloneDataStorage.h" #include "mitkDataNode.h" #include "mitkInteractor.h" #include "mitkDataInteractor.h" #include "mitkVtkPropRenderer.h" +#include "mitkBaseRenderer.h" #include "mitkTestingMacros.h" #include "mitkGlobalInteraction.h" +#include "itkLightObject.h" +#include "mitkDispatcher.h" int mitkDispatcherTest(int /*argc*/, char* /*argv*/[]) { MITK_TEST_BEGIN("Dispatcher") /* * Tests the process of creating Interactors and assigning DataNodes to them. * Test checks if these Interactors are added to the Dispatcher under different conditions, * and in different call order. */ // Global interaction must(!) be initialized if used mitk ::GlobalInteraction::GetInstance()->Initialize("global"); // Here BindDispatcherInteractor and Dispatcher should be created automatically vtkRenderWindow* renWin = vtkRenderWindow::New(); mitk::VtkPropRenderer::Pointer renderer = mitk::VtkPropRenderer::New( "ContourRenderer",renWin, mitk::RenderingManager::GetInstance() ); mitk::StandaloneDataStorage::Pointer ds = mitk::StandaloneDataStorage::New(); mitk::DataNode::Pointer dn = mitk::DataNode::New(); mitk::DataNode::Pointer dn2 = mitk::DataNode::New(); mitk::DataInteractor::Pointer ei = mitk::DataInteractor::New(); mitk::DataInteractor::Pointer ei2 = mitk::DataInteractor::New(); MITK_TEST_CONDITION_REQUIRED( renderer->GetDispatcher()->GetNumberOfInteractors() == 0 , "01 Check Existence of Dispatcher." ); ei->SetDataNode(dn); renderer->SetDataStorage(ds); ds->Add(dn); int num = renderer->GetDispatcher()->GetNumberOfInteractors(); MITK_TEST_CONDITION_REQUIRED( num == 1 , "02 Number of registered Interactors " << num << " , expected 1" ); // This _must not_ result in additionally registered interactors. ei->SetDataNode(dn); ei->SetDataNode(dn); num = renderer->GetDispatcher()->GetNumberOfInteractors(); MITK_TEST_CONDITION_REQUIRED( num == 1 , "03 Number of registered Interactors " << num << " , expected 1" ); // Switching the DataNode of an Interactor also must not result in extra registered Interactors in Dispatcher // since dn2 is not connected to DataStorage // ei will be dropped from dispatcher ei->SetDataNode(dn2); num = renderer->GetDispatcher()->GetNumberOfInteractors(); MITK_TEST_CONDITION_REQUIRED( num == 0 , "04 Number of registered Interactors " << num << " , expected 0" ); // DataNode Added to DataStorage, now Interactor entry in Dispatcher should be replaced, // hence we restore Interactor in the Dispatcher ds->Add(dn2); num = renderer->GetDispatcher()->GetNumberOfInteractors(); MITK_TEST_CONDITION_REQUIRED( num == 1 , "05 Number of registered Interactors " << num << " , expected 1" ); // New DataNode and new interactor, this should result in additional Interactor in the Dispatcher. ei2->SetDataNode(dn); num = renderer->GetDispatcher()->GetNumberOfInteractors(); MITK_TEST_CONDITION_REQUIRED( num == 2 , "06 Number of registered Interactors " << num << " , expected 2" ); // Here ei and ei2 point to the same dn2; dn2 now only points to ei2, so ei is abandoned, // therefore ei1 is expected to be removed ei2->SetDataNode(dn2); num = renderer->GetDispatcher()->GetNumberOfInteractors(); MITK_TEST_CONDITION_REQUIRED( num == 1 , "07 Number of registered Interactors " << num << " , expected 1" ); // Setting DataNode in Interactor to NULL, should remove Interactor from Dispatcher ei2->SetDataNode(NULL); num = renderer->GetDispatcher()->GetNumberOfInteractors(); MITK_TEST_CONDITION_REQUIRED( num == 0 , "08 Number of registered Interactors " << num << " , expected 0" ); renWin->Delete(); // always end with this! MITK_TEST_END() } diff --git a/Core/Code/files.cmake b/Core/Code/files.cmake index e9bc744796..5ca0ce8172 100644 --- a/Core/Code/files.cmake +++ b/Core/Code/files.cmake @@ -1,357 +1,355 @@ set(H_FILES Algorithms/itkImportMitkImageContainer.h Algorithms/itkImportMitkImageContainer.txx Algorithms/itkLocalVariationImageFilter.h Algorithms/itkLocalVariationImageFilter.txx Algorithms/itkMITKScalarImageToHistogramGenerator.h Algorithms/itkMITKScalarImageToHistogramGenerator.txx Algorithms/itkTotalVariationDenoisingImageFilter.h Algorithms/itkTotalVariationDenoisingImageFilter.txx Algorithms/itkTotalVariationSingleIterationImageFilter.h Algorithms/itkTotalVariationSingleIterationImageFilter.txx Algorithms/mitkBilateralFilter.h Algorithms/mitkBilateralFilter.cpp Algorithms/mitkInstantiateAccessFunctions.h Algorithms/mitkPixelTypeList.h # Preprocessor macros taken from Boost Algorithms/mitkPPArithmeticDec.h Algorithms/mitkPPArgCount.h Algorithms/mitkPPCat.h Algorithms/mitkPPConfig.h Algorithms/mitkPPControlExprIIf.h Algorithms/mitkPPControlIf.h Algorithms/mitkPPControlIIf.h Algorithms/mitkPPDebugError.h Algorithms/mitkPPDetailAutoRec.h Algorithms/mitkPPDetailDMCAutoRec.h Algorithms/mitkPPExpand.h Algorithms/mitkPPFacilitiesEmpty.h Algorithms/mitkPPFacilitiesExpand.h Algorithms/mitkPPLogicalBool.h Algorithms/mitkPPRepetitionDetailDMCFor.h Algorithms/mitkPPRepetitionDetailEDGFor.h Algorithms/mitkPPRepetitionDetailFor.h Algorithms/mitkPPRepetitionDetailMSVCFor.h Algorithms/mitkPPRepetitionFor.h Algorithms/mitkPPSeqElem.h Algorithms/mitkPPSeqForEach.h Algorithms/mitkPPSeqForEachProduct.h Algorithms/mitkPPSeq.h Algorithms/mitkPPSeqEnum.h Algorithms/mitkPPSeqSize.h Algorithms/mitkPPSeqToTuple.h Algorithms/mitkPPStringize.h Algorithms/mitkPPTupleEat.h Algorithms/mitkPPTupleElem.h Algorithms/mitkPPTupleRem.h Algorithms/mitkClippedSurfaceBoundsCalculator.h Algorithms/mitkExtractSliceFilter.h Algorithms/mitkConvert2Dto3DImageFilter.h Algorithms/mitkPlaneClipping.h Common/mitkExceptionMacro.h Common/mitkServiceBaseObject.h Common/mitkTestingMacros.h DataManagement/mitkImageAccessByItk.h DataManagement/mitkImageCast.h DataManagement/mitkImagePixelAccessor.h DataManagement/mitkImagePixelReadAccessor.h DataManagement/mitkImagePixelWriteAccessor.h DataManagement/mitkImageReadAccessor.h DataManagement/mitkImageWriteAccessor.h DataManagement/mitkITKImageImport.h DataManagement/mitkITKImageImport.txx DataManagement/mitkImageToItk.h DataManagement/mitkImageToItk.txx Interactions/mitkEventMapperAddOn.h Interfaces/mitkIDataNodeReader.h IO/mitkPixelTypeTraits.h ) set(CPP_FILES Algorithms/mitkBaseDataSource.cpp Algorithms/mitkBaseProcess.cpp Algorithms/mitkDataNodeSource.cpp Algorithms/mitkGeometry2DDataToSurfaceFilter.cpp Algorithms/mitkHistogramGenerator.cpp Algorithms/mitkImageChannelSelector.cpp Algorithms/mitkImageSliceSelector.cpp Algorithms/mitkImageSource.cpp Algorithms/mitkImageTimeSelector.cpp Algorithms/mitkImageToImageFilter.cpp Algorithms/mitkPointSetSource.cpp Algorithms/mitkPointSetToPointSetFilter.cpp Algorithms/mitkRGBToRGBACastImageFilter.cpp Algorithms/mitkSubImageSelector.cpp Algorithms/mitkSurfaceSource.cpp Algorithms/mitkSurfaceToSurfaceFilter.cpp Algorithms/mitkUIDGenerator.cpp Algorithms/mitkVolumeCalculator.cpp Algorithms/mitkClippedSurfaceBoundsCalculator.cpp Algorithms/mitkExtractSliceFilter.cpp Algorithms/mitkConvert2Dto3DImageFilter.cpp Controllers/mitkBaseController.cpp Controllers/mitkCallbackFromGUIThread.cpp Controllers/mitkCameraController.cpp Controllers/mitkCameraRotationController.cpp Controllers/mitkCoreActivator.cpp Controllers/mitkFocusManager.cpp Controllers/mitkLimitedLinearUndo.cpp Controllers/mitkOperationEvent.cpp Controllers/mitkPlanePositionManager.cpp Controllers/mitkProgressBar.cpp Controllers/mitkRenderingManager.cpp Controllers/mitkSliceNavigationController.cpp Controllers/mitkSlicesCoordinator.cpp Controllers/mitkSlicesRotator.cpp Controllers/mitkSlicesSwiveller.cpp Controllers/mitkStatusBar.cpp Controllers/mitkStepper.cpp Controllers/mitkTestManager.cpp Controllers/mitkUndoController.cpp Controllers/mitkVerboseLimitedLinearUndo.cpp Controllers/mitkVtkInteractorCameraController.cpp Controllers/mitkVtkLayerController.cpp DataManagement/mitkAbstractTransformGeometry.cpp DataManagement/mitkAnnotationProperty.cpp DataManagement/mitkApplicationCursor.cpp DataManagement/mitkBaseData.cpp DataManagement/mitkBaseProperty.cpp DataManagement/mitkClippingProperty.cpp DataManagement/mitkChannelDescriptor.cpp DataManagement/mitkColorProperty.cpp DataManagement/mitkDataStorage.cpp #DataManagement/mitkDataTree.cpp DataManagement/mitkDataNode.cpp DataManagement/mitkDataNodeFactory.cpp #DataManagement/mitkDataTreeStorage.cpp DataManagement/mitkDisplayGeometry.cpp DataManagement/mitkEnumerationProperty.cpp DataManagement/mitkGeometry2D.cpp DataManagement/mitkGeometry2DData.cpp DataManagement/mitkGeometry3D.cpp DataManagement/mitkGeometryData.cpp DataManagement/mitkGroupTagProperty.cpp DataManagement/mitkImage.cpp DataManagement/mitkImageAccessorBase.cpp DataManagement/mitkImageCaster.cpp DataManagement/mitkImageCastPart1.cpp DataManagement/mitkImageCastPart2.cpp DataManagement/mitkImageCastPart3.cpp DataManagement/mitkImageCastPart4.cpp DataManagement/mitkImageDataItem.cpp DataManagement/mitkImageDescriptor.cpp DataManagement/mitkImageVtkAccessor.cpp DataManagement/mitkImageStatisticsHolder.cpp DataManagement/mitkLandmarkBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjectorBasedCurvedGeometry.cpp DataManagement/mitkLandmarkProjector.cpp DataManagement/mitkLevelWindow.cpp DataManagement/mitkLevelWindowManager.cpp DataManagement/mitkLevelWindowPreset.cpp DataManagement/mitkLevelWindowProperty.cpp DataManagement/mitkLookupTable.cpp DataManagement/mitkLookupTables.cpp # specializations of GenericLookupTable DataManagement/mitkMemoryUtilities.cpp DataManagement/mitkModalityProperty.cpp DataManagement/mitkModeOperation.cpp DataManagement/mitkNodePredicateAnd.cpp DataManagement/mitkNodePredicateBase.cpp DataManagement/mitkNodePredicateCompositeBase.cpp DataManagement/mitkNodePredicateData.cpp DataManagement/mitkNodePredicateDataType.cpp DataManagement/mitkNodePredicateDimension.cpp DataManagement/mitkNodePredicateFirstLevel.cpp DataManagement/mitkNodePredicateNot.cpp DataManagement/mitkNodePredicateOr.cpp DataManagement/mitkNodePredicateProperty.cpp DataManagement/mitkNodePredicateSource.cpp DataManagement/mitkPlaneOrientationProperty.cpp DataManagement/mitkPlaneGeometry.cpp DataManagement/mitkPlaneOperation.cpp DataManagement/mitkPointOperation.cpp DataManagement/mitkPointSet.cpp DataManagement/mitkProperties.cpp DataManagement/mitkPropertyList.cpp DataManagement/mitkRestorePlanePositionOperation.cpp DataManagement/mitkRotationOperation.cpp DataManagement/mitkSlicedData.cpp DataManagement/mitkSlicedGeometry3D.cpp DataManagement/mitkSmartPointerProperty.cpp DataManagement/mitkStandaloneDataStorage.cpp DataManagement/mitkStateTransitionOperation.cpp DataManagement/mitkStringProperty.cpp DataManagement/mitkSurface.cpp DataManagement/mitkSurfaceOperation.cpp DataManagement/mitkThinPlateSplineCurvedGeometry.cpp DataManagement/mitkTimeSlicedGeometry.cpp DataManagement/mitkTransferFunction.cpp DataManagement/mitkTransferFunctionProperty.cpp DataManagement/mitkTransferFunctionInitializer.cpp DataManagement/mitkVector.cpp DataManagement/mitkVtkInterpolationProperty.cpp DataManagement/mitkVtkRepresentationProperty.cpp DataManagement/mitkVtkResliceInterpolationProperty.cpp DataManagement/mitkVtkScalarModeProperty.cpp DataManagement/mitkVtkVolumeRenderingProperty.cpp DataManagement/mitkWeakPointerProperty.cpp DataManagement/mitkShaderProperty.cpp DataManagement/mitkResliceMethodProperty.cpp DataManagement/mitkMaterial.cpp Interactions/mitkAction.cpp Interactions/mitkAffineInteractor.cpp Interactions/mitkBindDispatcherInteractor.cpp Interactions/mitkCoordinateSupplier.cpp Interactions/mitkDataInteractor.cpp Interactions/mitkDispatcher.cpp Interactions/mitkDisplayCoordinateOperation.cpp Interactions/mitkDisplayInteractor.cpp Interactions/mitkDisplayPositionEvent.cpp # Interactions/mitkDisplayVectorInteractorLevelWindow.cpp # legacy, prob even now unneeded # Interactions/mitkDisplayVectorInteractorScroll.cpp Interactions/mitkEvent.cpp Interactions/mitkEventConfig.cpp Interactions/mitkEventDescription.cpp Interactions/mitkEventFactory.cpp - Interactions/mitkEventHandler.cpp - Interactions/mitkEventObserver.cpp + Interactions/mitkInteractionEventHandler.cpp Interactions/mitkEventMapper.cpp Interactions/mitkEventStateMachine.cpp Interactions/mitkGlobalInteraction.cpp - Interactions/mitkInformer.cpp Interactions/mitkInteractor.cpp Interactions/mitkInternalEvent.cpp Interactions/mitkInteractionEvent.cpp Interactions/mitkInteractionPositionEvent.cpp Interactions/mitkInteractionKeyEvent.cpp Interactions/mitkMousePressEvent.cpp Interactions/mitkMouseMoveEvent.cpp Interactions/mitkMouseReleaseEvent.cpp Interactions/mitkMouseWheelEvent.cpp Interactions/mitkMouseModeSwitcher.cpp Interactions/mitkMouseMovePointSetInteractor.cpp Interactions/mitkMoveBaseDataInteractor.cpp Interactions/mitkNodeDepententPointSetInteractor.cpp Interactions/mitkPointSetDataInteractor.cpp Interactions/mitkPointSetInteractor.cpp Interactions/mitkPositionEvent.cpp Interactions/mitkPositionTracker.cpp Interactions/mitkStateMachineAction.cpp Interactions/mitkStateMachineState.cpp Interactions/mitkStateMachineTransition.cpp Interactions/mitkState.cpp -# Interactions/mitkStatedEventObserver.cpp Interactions/mitkStateMachineContainer.cpp Interactions/mitkStateEvent.cpp Interactions/mitkStateMachine.cpp Interactions/mitkStateMachineFactory.cpp Interactions/mitkTransition.cpp Interactions/mitkWheelEvent.cpp Interactions/mitkKeyEvent.cpp Interactions/mitkVtkEventAdapter.cpp Interactions/mitkVtkInteractorStyle.cxx Interactions/mitkCrosshairPositionEvent.cpp + + Interfaces/mitkInteractionEventObserver.cpp + IO/mitkBaseDataIOFactory.cpp IO/mitkCoreDataNodeReader.cpp IO/mitkDicomSeriesReader.cpp IO/mitkFileReader.cpp IO/mitkFileSeriesReader.cpp IO/mitkFileWriter.cpp #IO/mitkIpPicGet.c IO/mitkImageGenerator.cpp IO/mitkImageWriter.cpp IO/mitkImageWriterFactory.cpp IO/mitkItkImageFileIOFactory.cpp IO/mitkItkImageFileReader.cpp IO/mitkItkLoggingAdapter.cpp IO/mitkItkPictureWrite.cpp IO/mitkIOUtil.cpp IO/mitkLookupTableProperty.cpp IO/mitkOperation.cpp #IO/mitkPicFileIOFactory.cpp #IO/mitkPicFileReader.cpp #IO/mitkPicFileWriter.cpp #IO/mitkPicHelper.cpp #IO/mitkPicVolumeTimeSeriesIOFactory.cpp #IO/mitkPicVolumeTimeSeriesReader.cpp IO/mitkPixelType.cpp IO/mitkPointSetIOFactory.cpp IO/mitkPointSetReader.cpp IO/mitkPointSetWriter.cpp IO/mitkPointSetWriterFactory.cpp IO/mitkRawImageFileReader.cpp IO/mitkStandardFileLocations.cpp IO/mitkSTLFileIOFactory.cpp IO/mitkSTLFileReader.cpp IO/mitkSurfaceVtkWriter.cpp IO/mitkSurfaceVtkWriterFactory.cpp IO/mitkVtkLoggingAdapter.cpp IO/mitkVtiFileIOFactory.cpp IO/mitkVtiFileReader.cpp IO/mitkVtkImageIOFactory.cpp IO/mitkVtkImageReader.cpp IO/mitkVtkSurfaceIOFactory.cpp IO/mitkVtkSurfaceReader.cpp IO/vtkPointSetXMLParser.cpp IO/mitkLog.cpp Rendering/mitkBaseRenderer.cpp - Rendering/mitkVtkMapper2D.cpp - Rendering/mitkVtkMapper3D.cpp + Rendering/mitkVtkMapper.cpp Rendering/mitkRenderWindowFrame.cpp Rendering/mitkGeometry2DDataMapper2D.cpp Rendering/mitkGeometry2DDataVtkMapper3D.cpp - Rendering/mitkGLMapper2D.cpp + Rendering/mitkGLMapper.cpp Rendering/mitkGradientBackground.cpp Rendering/mitkManufacturerLogo.cpp - Rendering/mitkMapper2D.cpp - Rendering/mitkMapper3D.cpp Rendering/mitkMapper.cpp Rendering/mitkPointSetGLMapper2D.cpp Rendering/mitkPointSetVtkMapper3D.cpp Rendering/mitkPolyDataGLMapper2D.cpp Rendering/mitkSurfaceGLMapper2D.cpp Rendering/mitkSurfaceVtkMapper3D.cpp Rendering/mitkVolumeDataVtkMapper3D.cpp Rendering/mitkVtkPropRenderer.cpp Rendering/mitkVtkWidgetRendering.cpp Rendering/vtkMitkRectangleProp.cpp Rendering/vtkMitkRenderProp.cpp Rendering/mitkVtkEventProvider.cpp Rendering/mitkRenderWindow.cpp Rendering/mitkRenderWindowBase.cpp Rendering/mitkShaderRepository.cpp Rendering/mitkImageVtkMapper2D.cpp Rendering/vtkMitkThickSlicesFilter.cpp Rendering/vtkMitkLevelWindowFilter.cpp Rendering/vtkNeverTranslucentTexture.cpp + Rendering/mitkRenderingTestHelper.cpp Common/mitkException.cpp Common/mitkCommon.h Common/mitkCoreObjectFactoryBase.cpp Common/mitkCoreObjectFactory.cpp ) list(APPEND CPP_FILES ${CppMicroServices_SOURCES}) set(RESOURCE_FILES Interactions/globalConfig.xml Interactions/DisplayInteraction.xml Interactions/DisplayConfig.xml Interactions/DisplayConfigPACS.xml Interactions/DisplayConfigPACSPan.xml Interactions/DisplayConfigPACSScroll.xml Interactions/DisplayConfigPACSZoom.xml Interactions/DisplayConfigPACSLevelWindow.xml Interactions/DisplayConfigMITK.xml Interactions/PointSet.xml Interactions/Legacy/StateMachine.xml Interactions/PointSetConfig.xml Interactions/Tests/AddAndRemovePoints.xml Interactions/Tests/globalConfig.xml Interactions/Tests/StatemachineTest.xml Interactions/Tests/StatemachineConfigTest.xml ) diff --git a/Core/Documentation/Doxygen/Concepts/Concepts.dox b/Core/Documentation/Doxygen/Concepts/Concepts.dox index 2665de8898..b435bffaa9 100644 --- a/Core/Documentation/Doxygen/Concepts/Concepts.dox +++ b/Core/Documentation/Doxygen/Concepts/Concepts.dox @@ -1,32 +1,29 @@ /** \page Concepts MITK Concepts The following items describe some issues about MITK on a more abstract level. -# \subpage OverviewPage -# \subpage CodingPage "Coding Concepts" -# \ref CodingPageGeneral -# \ref CodingPageStyle -# \ref CodingPageMITKMacros -# \subpage MicroServices_Overview -# Data Concepts -# \subpage DataManagementPage -# \subpage MitkImagePage -# \subpage PropertiesPage -# \subpage GeometryOverviewPage -# \subpage PipelineingConceptPage -# \subpage QVTKRendering -# Interaction -# \subpage DataInteractionPage -# \subpage InteractionPage -# \subpage LoggingPage -# \subpage ExceptionPage --# Testing Concept - -# \subpage GeneralTests - -# \subpage RenderingTests -# \subpage ModularizationPage "Modularization Concept" -# \ref ModularizationPageOverview -# \ref ModularizationPageHowTo If you want to start using MITK, you also want to see the chapter \ref Development. */ diff --git a/Core/Documentation/Doxygen/Concepts/DataInteraction.dox b/Core/Documentation/Doxygen/Concepts/DataInteraction.dox index 46adae02d9..6c74c6b905 100644 --- a/Core/Documentation/Doxygen/Concepts/DataInteraction.dox +++ b/Core/Documentation/Doxygen/Concepts/DataInteraction.dox @@ -1,204 +1,204 @@ /** \page DataInteractionPage Interaction Concepts \tableofcontents \section InteractionPage_Introduction Introduction to Interaction in MITK Interaction is a very important task in medical image processing software. Therefore MITK provides a special interaction concept that provides the developer with an easy way to develop and maintain user interaction separately from the algorithms processing the input. This allows e.g. for common interaction schemes to be re-used in different contexts. The core of the interaction concept is based on entities called \b DataInteractors that listen for certain pre-defined events and execute actions when such an event is triggered.\n In the following the different components of the interaction concept are explained. First a a high-level overview about how the different components interact is given, then some parts are explained in more detail. \subsection FurtherReadingInteraction Topics related to interaction - further information: See the \ref DataInteractionTechnicalPage page for a more technical explanation. \n Consult \ref HowToUseDataInteractor for usage information.\n See \ref SectionImplementationDataInteractor for an example on how to implement a new DataInteractor \n for information about how to create new events refer to ImplementNewEventsPage.\n The documentation of the depricated former concept can be found at \ref InteractionPage. \section HandlingSection Event Handling & Window Manager Abstraction The following sequence diagram gives an examplary overview of the process from creating an event until executing an action in the DataInteractor. This diagram assumes the usage of the Qt framework, but also shows that the interaction concept itself is implemented independent of any specific window manager. \image html event_handling.png
  1. a user event is triggered and send to MITK
  2. this layler serves as an adapter from window manager (here Qt) events to MITK internal events (later refered to as InteractionEvents).
  3. once the event is adapted it is send to a Dispatcher, which is linked to a render window, to be handled.
  4. on Dispatcher level all objects are known that can react to incoming events (DataInteractors)
  5. a DataInteractor is offered an event and checks its EventConfig object, which returns if a variant if this event has been defined for this DataInteractor.
  6. if the DataInteractor has a variant for the event, it consults its state machine to check if the input can be handled in the current state
  7. the actions asociated with a state change (transition) are executed and the event is successfully handled.
\section EventPage Events Events can describe any sort of user input, such as key strokes, mouse clicks or touch gestures. These events are mapped from an UI framework like Qt to an MITK internal representation and send to the Dispatcher which in turn deals with further processing of the event. These events are not limited to classical input devices but can be extened at will, by introducing new classes which e.g. describe -events from tracking devices, etc. Refer to \ref ImplementNewEventsPage to see how new events and thereby input devices can be integrated. -For an overview of available Events see mitk::InteractionEvent, for on overview of parameters see the \ref DataInteractionTechnicalPage. +events from tracking devices, etc. Refer to \subpage ImplementNewEventsPage to see how new events and thereby input devices can be integrated. +For an overview of available Events see mitk::InteractionEvent, for on overview of parameters see the \subpage DataInteractionTechnicalPage. -\section EventHandlerSection EventHandler +\section InteractionEventHandlerSection InteractionEventHandler Is the term describing objects in general that can handle events. These objects can be devided into two groups, namely -DataInteractors and EventObserver. Their difference is that DataInteractors are linked with a DataNode which they manipulate, -whereas EventObserver do not have a DataNode and therefore are not supposed to manipulate any data. +DataInteractors and InteractionEventObserver. Their difference is that DataInteractors are linked with a DataNode which they manipulate, +whereas InteractionEventObserver do not have a DataNode and therefore are not supposed to manipulate any data. \dot digraph linker_deps { node [shape=record, fontname=Helvetica, fontsize=10]; - a [ label="EventHandler" ]; + a [ label="InteractionEventHandler" ]; d [ label="{StateMachine|HandleEvent()}" ]; b [ label="{DataInteractor|HandleEvent()}" ]; - c [ label="{EventObserver|Notify()}" ]; + c [ label="{InteractionEventObserver|Notify()}" ]; a -> d; d -> b; d -> c; } \enddot \subsection DataInteractorsSection DataInteractors -DataInteractors are specialized EventHandler which handle events for one spefific DataNode. They are implemented following a concept called state machines +DataInteractors are specialized InteractionEventHandler which handle events for one spefific DataNode. They are implemented following a concept called state machines (see e.g. Wikipedia ). \subsubsection StateMachinesSection StateMachines A specific events action is usually desired to dependent on the content of the data object the state of the interaction. For example if the when adding a line by clicking with the mouse, the first to clicks are supposed to add a point. But the second click should additionally finish the interaction and a subsequent third click should be ignored. State machines provide a great way to model such interaction in which the same user interaction can trigger different actions depending on the current state. Therefore DataInteractors work with so called state machine patterns. The basic idea here is that each interaction can be described by states and transitions which in turn trigger actions. These patterns define a workflow and different patterns can be applied to the same DataInteractor and cause this DataInteractor to perform different user interactions. This principle is best described by an example. Imagine a DataInteractor with the functionality (1) to add Points at a given mouse position and connect them by a line and (2) check if two points are on the same position. Using this DataInteractor, different StateMachine patterns/descriptions can be given which each cause the DataInteractor to perform different interaction schemes. State machine pattern 1: We want the user to draw a line. A simple state machine could express this by three states like this: \dot digraph linker_deps { node [shape=circle, fontname=Helvetica, fontsize=10]; a [ label="NoPoints" ]; b [ label="OnePoint" ]; c [ label="TwoPoints" ]; a -> b [label="MousePress/AddPoint",fontname=Helvetica, fontsize=10]; b -> c [label="MousePress/AddPoint",fontname=Helvetica, fontsize=10]; { rank=same; a b c } } \enddot With each MousePress event the AddPoint function is called and adds a point at the mouse position, unless two points already exist. State machine pattern 2: The same DataInteractor can also operate after the following state machine, which models the interaction to input a closed contour. The DataInteractor can detect an AddPoint event on an already existing point and will trigger a PointsMatch event. \dot digraph { node [shape=circle, fontname=Helvetica, fontsize=10]; a [ label="StartState" ]; b [ label="ClosedContour"]; a -> a [label="MousePress/AddPoint",fontname=Helvetica, fontsize=10]; a -> b [label="PointsMatch/AddPoint",fontname=Helvetica, fontsize=10]; } \enddot In this way state machines provide both, a nice and structured way to represent interaction tasks and description of the interaction which is separated from the code. One DataInteractor can be re-used for different tasks by simply exchanging the state machine pattern. These patterns are described in XML files. \subsubsection DefinitionStateMachine Definition of a State Machine The definition is made up out of three components.
  • States - represent the current status of the interaction
  • Transitions - describe the events needed to change from one state to another
  • Actions - are executed, when a transition is taken
Each state machine needs exactly one designated start state into which the state machine is set in the beginning. An example of a state machine describing the interaction of example 2 looks like this: \code \endcode Example 1: State machine pattern, that describes adding points to a contour until the PointsMatch event is triggered. For a more detailed desciption of state machine patterns see here. -\subsection EventObserverSection EventObserver +\subsection InteractionEventObserverSection InteractionEventObserver -EventObserver are objects which will receive all user input and are intented for observation only, they should never modify any DataNodes. -For EventObserver it is optional to use the state machine functionality, the default is without. How to use the state machine functionality - is described in the documentation of mitk::EventObserver::Notify. +InteractionEventObserver are objects which will receive all user input and are intented for observation only, they should never modify any DataNodes. +For InteractionEventObserver it is optional to use the state machine functionality, the default is without. How to use the state machine functionality + is described in the documentation of mitk::InteractionEventObserver::Notify. \subsection ConfigurationSection Configuration In a lot of cases it is preferable to implement interactions independent of a specific event (e.g. left click with mouse), such that is it possible -to easily change this. This is achieved through configuration of EventHandlers. This allows to change the behavior at runtime. -The EventHandler provides an interface to easily modify the user input that triggers an action by loading a different configuration, this allows to implement +to easily change this. This is achieved through configuration of InteractionEventHandlers. This allows to change the behavior at runtime. +The InteractionEventHandler provides an interface to easily modify the user input that triggers an action by loading a different configuration, this allows to implement user-specific behavior of the software on an abstract level and to switch in at runtime. -This is achieved through XML files describing a configuration. These files can be loaded by the EventHandler and will lead to an internal mapping +This is achieved through XML files describing a configuration. These files can be loaded by the InteractionEventHandler and will lead to an internal mapping from specific user input to an absract description of the event given in the config file. In order to do this we distinguish between a spefic event and an event variant. A specific event is described by its event class, which determines the category of an event, e.g. the class MousePressEvent, and its parameter which make this event unique, e.g. LeftMouseButton pressed and no modifier keys pressed. -The event variant is a name that is assigned to a spefific event, and to which an EventHandler listens. +The event variant is a name that is assigned to a spefific event, and to which an InteractionEventHandler listens. -To illustrate this, an example is given here for two different configuration files. We assume an EventHandler that listens to the event variant 'AddPoint', +To illustrate this, an example is given here for two different configuration files. We assume an InteractionEventHandler that listens to the event variant 'AddPoint', two possible config files could then look like this: \code - + - + \endcode Example 2: Event description of a left click with the mouse and \code - + - + \endcode Example 3: Event description of a left click with the mouse while pressing the shift-key -If the EventHandler is loaded with the first configuration the event variant 'MousePress' is triggered when the user performs a mouse click, +If the InteractionEventHandler is loaded with the first configuration the event variant 'MousePress' is triggered when the user performs a mouse click, while when the second configuration is loaded 'MousePress' is triggered when the user performs a right click while pressing the shift button. -In this way all objects derived by EventHandler can be configured. For a detailed description about how to create the XML file see \ref ConfigurationTechnical . +In this way all objects derived by InteractionEventHandler can be configured. For a detailed description about how to create the XML file see \ref ConfigurationTechnical . \section DispatcherSection Dispatcher This unit receives all events and distributes them to the DataInteractors. This is done by ordering the DataInteractors according to the layer of their DataNode in descending order. Then the event is offered to the first DataInteractor, which in turn checks if it can handle the event. This is done -for each DataInteractor until the first processes the event, after this the other DataInteractors are skipped and all EventObservers are notified. +for each DataInteractor until the first processes the event, after this the other DataInteractors are skipped and all InteractionEventObservers are notified. */ diff --git a/Core/Documentation/Doxygen/Concepts/NewEvents.dox b/Core/Documentation/Doxygen/Concepts/NewEvents.dox index 2f7992c126..cb42cb550a 100644 --- a/Core/Documentation/Doxygen/Concepts/NewEvents.dox +++ b/Core/Documentation/Doxygen/Concepts/NewEvents.dox @@ -1,56 +1,72 @@ /** \page ImplementNewEventsPage What needs to be done to implement a new event? \tableofcontents \section WhenUseEvents When to use this guide In general there are no restriction about how events are created and processed. The intention of this page is to provide how to contruct Events in order to use them with the MITK Interaction Concept. \section OriginEvents Origin and processing of Events \ref DataInteractionPage gives a brief description of how events are generated and proccessed. After events are created they need to be send via mitk::RenderWindowBase::HandleEvent() so that they are relayed to a Dispatcher which handles the event distribution to the DataInteractors. \section EventImplementation Event Implementation The only prerequisite for a new event to be accepted is that it is derived from the mitk::InteractionEvent class. Further it is neccessary to provide a unique string identifier for this event class -(this string will identify this class/super-class in a state machine pattern by the event_class tag), and it needs to implement at least one function, +(this string will identify this class/super-class in a state machine pattern by the event_class tag), and it needs to implement at least two functions, as shown at the example of the MousePressEvent. Implementation of equality for each event class by implementing isEqual. Equality does \b not mean an exact copy or pointer equality. Equality is determined by agreement in all attributes that are necessary to describe the event for a state machine transition. Here, for example, for the a mouse event press event, it is important which modifiers are used, which mouse button was used to triggered the event, but the mouse position is irrelevant. \code bool mitk::MousePressEvent::MatchesTemplate(mitk::InteractionEvent::Pointer interactionEvent) { // cast to your event class here mitk::MousePressEvent* mpe = dynamic_cast(interactionEvent.GetPointer()); if (mpe == NULL) { return false; } // Checking relevant attributes, such as EventButton and Modifiers, but omitting the mouse coordinates // Replace this to check for your event class' attributes return (this->GetEventButton() == mpe->GetEventButton() && this->GetModifiers() == mpe->GetModifiers() && this->GetButtonStates() == mpe->GetButtonStates()); } \endcode +The function IsSuperClassOf() implements an up cast to check if the provided baseClass object is derived from this class. +This function is used to support polymorphism on state machine pattern (XML) level. + +\code +bool mitk::MousePressEvent::IsSuperClassOf(InteractionEvent::Pointer baseClass) +{ + // Replace with your class, or implement some rules which classes are accepted. + MousePressEvent* event = dynamic_cast(baseClass.GetPointer()); + if (event != NULL) + { + return true; + } + return false; +} +\endcode + \section EventConstruction Configuration File & Event Factory Regarding the state machine and the state machine pattern parser there are no changes necessary. To be able to parse the new event, changes have to be made in the mitk::EventConfig and mitk::EventFactory classes. The mitk::EventConfig class has to be adapted in a way such that the parameters that describe the event are parsed. The parsing can be easily extended, and should provide a mitk::PropertyList for each event parsed. Lastly the mitk::EventFactory has to be extended to use this mitk::PropertyList and construct an event based on it. */ diff --git a/Documentation/Doxygen/Modules/ModuleAdaptors.dox b/Core/Documentation/Doxygen/Groups/ModuleAdaptors.dox similarity index 98% rename from Documentation/Doxygen/Modules/ModuleAdaptors.dox rename to Core/Documentation/Doxygen/Groups/ModuleAdaptors.dox index c00107bc16..de2854d62b 100644 --- a/Documentation/Doxygen/Modules/ModuleAdaptors.dox +++ b/Core/Documentation/Doxygen/Groups/ModuleAdaptors.dox @@ -1,142 +1,139 @@ -namespace mitk -{ /** \defgroup Adaptor Adaptor Classes \ingroup ProcessAdaptor -\brief This subcategory includes adaptor classes for the integration of algorithms from +\brief This subcategory includes adaptor classes for the integration of algorithms from other toolkits, especially ITK. The task of most of the classes in this category is to deal with the conversion between the (templated) itk::Image and the (not-templated) mitk::Image. Methods for conversion are provided for both directions: \li \ref MitkToItk \li \ref ItkToMitk Care has to be taken regarding the involved coordinate systems, see \ref ItkToMitkCoordinateSystems. For limitations on ITK-type conversion see the section \ref ModuleAdaptorLimitations. VTK-based access to MITK images is straightforward: simply ask your mitk::Image for a -\a vtkImageData by calling Image:GetVtkImageData. Similarily, to get a \a vtkPolyData +\a vtkImageData by calling Image:GetVtkImageData. Similarily, to get a \a vtkPolyData from the MITK class for storing surfaces, mitk::Surface, call Surface::GetVtkPolyData. \section MitkToItk MITK to ITK adaptors Pixel type and dimension of MITK images can be specified at run time whereas ITK images are templated over the pixel type and the dimension, thus in ITK both need to be specified at compile time. There two different situations, which are covered in the following sub-sections: \li Either you know the pixel type/dimension the ITK image should have at compile time for some reason (e.g., you always create MITK images of a specific pixel type/dimension) \li or the pixel type/dimension of an MITK image is really unkown and the ITK image should have the same (unkown) type. \subsection MitkToFixedItk Converting MITK images to ITK images with known type If you know the type (pixel type and dimension) of the MITK image you have two options: \li mitk::ImageToItk: is a process class that takes an mitk::Image as input and produces an itk::Image of the given type \a TOutputImage as output (to be accessed using \a GetOutput()). In case the MITK image does not have the same type as \a TOutputImage an exception will be thrown. \li mitk::CastToItkImage: this function has two parameters, the mitk::Image (input) and a smartpointer to an itk::Image (output, does not need to be initialized). In case the - MITK image does not have the same type as the ITK image it will be casted + MITK image does not have the same type as the ITK image it will be casted (if possible; done via itk::CastImageFilter). Thus, mitk::CastToItkImage is the more powerful variant: here it is sufficient that you know what you want to have (the ITK data type), to which the MITK image will be casted, if needed. \subsection MitkToUnkownItk Accessing an MITK image as an ITK image (type unkown) If you do not know the pixel type/dimension of an MITK image in advance and the ITK image should have the same (unkown) type, e.g., to run a filter on the MITK image data, we cannot really convert to one ITK image. This is simply, because we cannot instantiate an itk::Image object with unkown pixel type/dimension. Nevertheless, MITK provides a way to access an MITK image as if it was an ITK image of unkown type. To do so, first define an access method, which is templated as an ITK image is: \code template MyAccessMethod(itk::Image* itkImage) { ... } \endcode If you don't understand this template syntax, we need to refer you to an C++ text book. Understanding template syntax is crucial to successfully using ITK. To call this templated method with an (untemplated) mitk::Image, you can use the #AccessByItk macro (or one of its variants) from mitkImageAccessByItk.h. This macro checks for the actual image type of the mitk::Image and does any neccessary conversions. This works for all configured pixel types (default is char, unsigned char, short, unsigned short, int, unsigned int, float, and double) and dimensions (default is 2 and 3). You can change the considered default pixel types and dimensions by modifying the CMake variables MITK_ACCESSBYITK_*. \code AccessByItk(mitkImage, MyAccessMethod) \endcode An example is given in \ref Step6Page. The AccessBy... macros create quite a lot of code: the user defined access method has to be compiled for all considered pixel types \em times the supported dimensions (default is 2 and 3). Therefore, depending on the complexity of the access method, some compilers may run into problems with memory. One workaround is to use explicit instantiation and distribute it on multiple files. The macro #InstantiateAccessFunction and its variants are for this purpose. An example is again given in \ref Step6Page. Another workaround is to reduce the created code by fixing either the type (#AccessFixedTypeByItk) or dimension (#AccessFixedDimensionByItk). There is one variant of AccessByItk... for passing additional parameters to the access-function, called #AccessFixedTypeByItk_n. \link mitkImage.h \endlink \link mitkImageCast.h \endlink \link mitkImageToItk.h \endlink \link mitkITKImageImport.h \endlink \section ItkToMitk ITK to MITK adaptors Converting ITK images to MITK is easier than the other way round. Basically, you have three options: \li mitk::ITKImageImport: is a process class that takes an itk::Image of the given type \a TOutputImage as input and produces an mitk::Image as output (to be accessed using \a GetOutput()). The image data contained in the itk::Image is referenced, not copied. \li mitk::ImportItkImage: this function takes the itk::Image as input and returns an mitk::Image. Internally, it uses the class just described. So again, the image data contained in the itk::Image is referenced, not copied. \li mitk::CastToMitkImage: this function has two parameters, the itk::Image (input) and a smartpointer to an mitk::Image (output, does not need to be initialized). In contrast to the other described methods, this function copies the image data! \section ItkToMitkCoordinateSystems ITK image vs MITK coordinate systems Converting coordinates from the ITK physical coordinate system (which does not support rotated images) to the MITK world coordinate system should be performed via the Geometry3D of the Image, see mitk::Geometry3D::WorldToItkPhysicalPoint. \section ModuleAdaptorLimitations Limitations The \ref MitkToItk for unspecified types have to do type multiplexing at compile time. This is done for a limited number of pixel types and dimensions, defined during the CMake configuration process. Especially, color image types are not multiplexed. This is because many algorithms do not support color images (e.g. with data type itk::RGBPixel) because they do not have a scalar data type. If your algorithm do support color and you want to multiplex over all scalar as well as the color data type, try the following: \code try { AccessFixedPixelTypeByItk(myMitkImageThatMaybeColor, // The MITK image which may be a color image myAlgorithmFunction, // The template method being able to handle color MITK_ACCESSBYITK_PIXEL_TYPES_SEQ // The default pixel type sequence (itk::RGBPixel) // The additional type sequence ) } catch(const mitk::AccessByItkException& e) { // add error handling here } \endcode */ -} diff --git a/Documentation/Doxygen/Modules/ModuleGeometry.dox b/Core/Documentation/Doxygen/Groups/ModuleGeometry.dox similarity index 97% rename from Documentation/Doxygen/Modules/ModuleGeometry.dox rename to Core/Documentation/Doxygen/Groups/ModuleGeometry.dox index 212dd043a4..988a18d3b3 100644 --- a/Documentation/Doxygen/Modules/ModuleGeometry.dox +++ b/Core/Documentation/Doxygen/Groups/ModuleGeometry.dox @@ -1,47 +1,47 @@ namespace mitk { /** \defgroup Geometry Geometry Classes -\ingroup DataManagement +\ingroup Core -\brief This subcategory includes the geometry classes, which describe the geometry of the +\brief This subcategory includes the geometry classes, which describe the geometry of the data in space and time. The Geometry3D class holds (see figure) \li a bounding box which is axes-parallel in intrinsic coordinates (often integer indices of pixels), to be accessed by Geometry3D::GetBoundingBox() \li a transform to convert intrinsic coordinates into a world-coordinate system with coordinates in millimeters and milliseconds (floating point values), to be accessed by Geometry3D::GetIndexToWorldTransform() \li a life span, i.e. a bounding box in time in ms (with start and end time), to be accessed by Geometry3D::GetTimeBounds(). The default is minus infinity to plus infinity. \image html ModuleGeometryFig1.png "Geometry: Bounding box and transform" Geometry3D and its sub-classes allow converting between intrinsic coordinates (called index or unit coordinates) and word-coordinates (called world or mm coordinates), e.g. Geometry3D::WorldToIndex. Every data object (sub-)class of BaseData has a Geometry3D, to be more specific, a TimeSlicedGeometry, to be accessed by BaseData::Get TimeSlicedGeometry(). This is because data objects are objects in space and time. The data values are often stored in intrinsic coordinates, e.g., integer pixel/voxel or time indices. The information required to convert these intrinsic coordinates into a physical world coordinate system, with coordinates in millimeters and milliseconds, is stored in Geometry3D class and its sub-classes. -TimeSlicedGeometry describes a geometry consisting of several geometries which exist at different times. It contains a list of Geometry3D instances to be accessed by TimeSlicedGeometry::GetGeometry3D(t), with t between 0 and TimeSlicedGeometry::GetTimeSteps().To convert between world-time in milliseconds and the integer timestep-number use mitk:TimeSlicedGeometry:: MSToTimeStep, for conversion in the opposite direction mitk:TimeSlicedGeometry:: TimeStepToMS. +TimeSlicedGeometry describes a geometry consisting of several geometries which exist at different times. It contains a list of Geometry3D instances to be accessed by TimeSlicedGeometry::GetGeometry3D(t), with t between 0 and TimeSlicedGeometry::GetTimeSteps().To convert between world-time in milliseconds and the integer timestep-number use mitk:TimeSlicedGeometry:: MSToTimeStep, for conversion in the opposite direction mitk:TimeSlicedGeometry:: TimeStepToMS. Often all Geometry3D instances contained in a TimeSlicedGeometry have the same duration of life. The initialization for this case can be done using TimeSlicedGeometry::InitializeEvenlyTimed(Geometry3D *geometry3D, unsigned int timeSteps). The Geometry3D parameter must have a limited life span set by Geometry3D::SetTimeBounds(). It is used as the first Geometry3D contained in the TimeSlicedGeometry (thus returned by TimeSlicedGeometry:: GetGeometry3D(0)). The next one will start to live immediately at the end of life of the first. The bounding boxes and transformations are copied. The instance of Geometry3D provided to TimeSlicedGeometry::InitializeEvenlyTimed is referenced, not copied! -TimeSlicedGeometry is a Geometry3D itself. Its bounding box and transformation is usually the same as the bounding box and transformations of the contained Geometry3D instances. Its life span (to be accessed by TimeSlicedGeometry::GetTimeBounds()) is the span from the beginning of the first contained Geometry3D to the end of the last contained Geometry3D. +TimeSlicedGeometry is a Geometry3D itself. Its bounding box and transformation is usually the same as the bounding box and transformations of the contained Geometry3D instances. Its life span (to be accessed by TimeSlicedGeometry::GetTimeBounds()) is the span from the beginning of the first contained Geometry3D to the end of the last contained Geometry3D. TimeSlicedGeometry can also contain Geometry3D instances that do not have the same bounding box and transformation. In this case, TimeSlicedGeometry::GetEvenlyTimed() has to be \a false. SlicedGeometry3D is a sub-class of Geometry3D, which descibes data objects consisting of slices, e.g., objects of type Image (or SlicedData, which is the super-class of Image). Therefore, Image::Get TimeSlicedGeometry() will contain a list of SlicedGeometry3D instances. There is a special method SlicedData::GetSlicedGeometry(t) which directly returns a SlicedGeometry3D to avoid the need of casting. Geometry instances referring to images need a slightly different definition of corners, see Geometry3D::SetImageGeometry. This is usualy automatically called by Image. -Comparable to TimeSlicedGeometry the class SlicedGeometry3D contains a list of Geometry2D objects describing the slices in the data object. Instead of time steps we have spatial steps here from 0 to GetSlices(). SlicedGeometry3D::InitializeEvenlySpaced (Geometry2D *geometry2D, unsigned int slices) initializes a stack of slices with the same thickness, one starting at the position where the previous one ends. +Comparable to TimeSlicedGeometry the class SlicedGeometry3D contains a list of Geometry2D objects describing the slices in the data object. Instead of time steps we have spatial steps here from 0 to GetSlices(). SlicedGeometry3D::InitializeEvenlySpaced (Geometry2D *geometry2D, unsigned int slices) initializes a stack of slices with the same thickness, one starting at the position where the previous one ends. Geometry2D provides methods for working with 2D manifolds (i.e., simply spoken, an object that can be described using a 2D coordinate-system) in 3D space. For example it allows mapping a 3D point on the 2D manifold using Geometry2D::Map. The most important sub-class is PlaneGeometry2D, which describes a planar rectangle. \section ExampleForImage Putting it together for Image Image has a TimeSlicedGeometry, which contains one or more SlicedGeometry3D instances (one for each time step), all of which contain one or more instances of (sub-classes of) Geometry2D (usually PlaneGeometry2D). \deprecated For ITK rev. 3.8 and earlier: Converting coordinates from the ITK physical coordinate system (which did not support rotated images for ITK v3.8 and earlier) to the MITK world coordinate system should be performed via the Geometry3D of the Image, see Geometry3D::WorldToItkPhysicalPoint. As a reminder: Geometry instances referring to images need a slightly different definition of corners, see Geometry3D::SetImageGeometry. This is usualy automatically called by Image. */ //\f$-\infty\f$ to \f$+\infty\f$. } diff --git a/Documentation/Doxygen/Modules/ModuleGeometryFig1.png b/Core/Documentation/Doxygen/Groups/ModuleGeometryFig1.png similarity index 100% rename from Documentation/Doxygen/Modules/ModuleGeometryFig1.png rename to Core/Documentation/Doxygen/Groups/ModuleGeometryFig1.png diff --git a/Documentation/Doxygen/Modules/ModuleMicroServices.dox b/Core/Documentation/Doxygen/Groups/ModuleMicroServices.dox similarity index 99% rename from Documentation/Doxygen/Modules/ModuleMicroServices.dox rename to Core/Documentation/Doxygen/Groups/ModuleMicroServices.dox index e3e6869d38..0e5d618203 100644 --- a/Documentation/Doxygen/Modules/ModuleMicroServices.dox +++ b/Core/Documentation/Doxygen/Groups/ModuleMicroServices.dox @@ -1,30 +1,29 @@ /** \addtogroup MicroServices \ingroup Core */ /** \addtogroup MicroServicesUtils \ingroup Core */ /** \defgroup MicroServices_Interfaces Micro Services Interfaces \ingroup Core \brief Classes (interfaces) in this category are explicitely designed for usage with the MITK Micro Services. All classes in this category are structs with no non-static members and only pure virtual functions (except for an inlined virtual destructor). Such a class will be called a \e interface. These interfaces are meant to be implemented by MITK module developers to enhance or overwrite certain aspects of the MITK toolkit. All implementations must be registered in the implementing module's \e activator (see mitk::ModuleActivator) using the module's mitk::ModuleContext instance. */ - diff --git a/Documentation/Doxygen/Modules/ModuleVisualization.dox b/Core/Documentation/Doxygen/Groups/ModuleVisualization.dox similarity index 80% rename from Documentation/Doxygen/Modules/ModuleVisualization.dox rename to Core/Documentation/Doxygen/Groups/ModuleVisualization.dox index b63b43f940..72fb312d85 100644 --- a/Documentation/Doxygen/Modules/ModuleVisualization.dox +++ b/Core/Documentation/Doxygen/Groups/ModuleVisualization.dox @@ -1,45 +1,45 @@ /** \defgroup Visualization Visualization and Visualization Organization Classes \ingroup Core -\brief This category includes renderwindows (currently one for OpenGL), renderers (currently only one, +\brief This category includes renderwindows (currently one for OpenGL), renderers (currently only one, for OpenGL-based renderwindows), mappers and classes for navigating in the data. \section overviewVisualization Rationale and overview -Mappers visualize data objects of a specific classes by creating rendering primitives that -interface to the graphics library (e.g., OpenGL, vtk). -Renderers organize the rendering process. A Renderer contains a reference to a (sub-) data tree +Mappers visualize data objects of a specific classes by creating rendering primitives that +interface to the graphics library (e.g., OpenGL, vtk). +Renderers organize the rendering process. A Renderer contains a reference to a (sub-) data tree and asks the mappers of the data objects to render the data into the renderwindow it is associated to. -More details can be found in the section on \ref Rendering. +More details can be found in the section on \ref Rendering. -\subsection inthisgroupVisualization What belongs into this group +\subsection inthisgroupVisualization What belongs into this group \section implementVisualization Practical issues -\section futureVisualization Plans for the future +\section futureVisualization Plans for the future - Abort mechanism - level-of-detail rendering mechanism - allow multiple renderers per renderwindow -- modified detection mechanism: +- modified detection mechanism: - allow to detect whether a modification of data/property/dislaygeometry /camera requires to re-render. E.g., mark whether a property effects the rendering. - analyze which type of modification requires which kind of action, e.g.: - if the displaygeometry or the color has changed, we do not need to - resample an image, but we do need to redraw. The first step is to + if the displaygeometry or the color has changed, we do not need to + resample an image, but we do need to redraw. The first step is to analyze which types of modifications (e.g., displaygeometry changed, properties changed; can we group these?) and actions exist. -- improved design of navigation controllers, probably more focused on +- improved design of navigation controllers, probably more focused on steppers (then on BaseController). Have in mind: - rotatable slices - - dependent views: e.g., sequence of renderers showing series of - consecutive slices (maybe realized as master stepper and + - dependent views: e.g., sequence of renderers showing series of + consecutive slices (maybe realized as master stepper and dependent offset steppers) - consider time vs. slice stepping - use stepper mechanism for additional purposes, e.g., for animating transfer functions */ diff --git a/Documentation/Doxygen/Modules/ModuleVisualizationMapper.dox b/Core/Documentation/Doxygen/Groups/ModuleVisualizationMapper.dox similarity index 98% rename from Documentation/Doxygen/Modules/ModuleVisualizationMapper.dox rename to Core/Documentation/Doxygen/Groups/ModuleVisualizationMapper.dox index a7a9dc1a2f..8f6a285c77 100644 --- a/Documentation/Doxygen/Modules/ModuleVisualizationMapper.dox +++ b/Core/Documentation/Doxygen/Groups/ModuleVisualizationMapper.dox @@ -1,25 +1,25 @@ /** \defgroup Mapper Mapper Classes \ingroup Visualization \brief In the MITK rendering concept, Mappers are responsible for actually rendering data onto the screen. \section overviewVisualizationMapper Overview Mappers differ in the type of data they are capable of rendering (e.g. volume data, polygonal data) and the mode of how data is rendered (e.g. 2D or 3D). For example, the ImageMapperGL2D renders volume data in a 2D view, i.e. it extracts a slice of the volume (as determined by the Geometry of the associated Renderer) and displays it as a 2D plane. All Mapper classes are arranged in a class hierarchy according to these criterions. \section integrationVisualizationMapper Integration into the rendering process Mapper objects are owned by the DataNode which contains the data they have to render. An overview over this composition is given in the section \ref Renderer. Each DataNode can have (and usually has) multiple Mappers attached, each responsible for different modes of rendering. In most cases this would be one 2D Mapper and one 3D Mapper, but other Mappers are possible, too. -Which Mapper of a DataNode to use is determined by an ID; the Renderer of a 2D window would for example ask the DataNode to return an appropriate 2D Mapper. +Which Mapper of a DataNode to use is determined by an ID; the Renderer of a 2D window would for example ask the DataNode to return an appropriate 2D Mapper. More details can be found in the section on \ref Rendering. \section todoVisualizationMapper Future plans The need to Update() a Mapper can be justified by property changes in the associated data items. However, property changes are not uniformly taken into account when deciding on whether to execute Update() or not. The changes are data specific and difficult to generalize. As an effect, many Update() calls are not really necessary and might slow down the rendering process significantly. One solution to this problem might be a mechanism which allows Mappers to register themselves to relevant data properties, so as to be notified whenever a change occurs. If no modification did occur since the last Update(), and the data itself has remained unchanged, no re-initialization (of the rendering pipeline for example) needs to be performed. */ diff --git a/Documentation/Doxygen/Modules/ModuleVisualizationNavigationControl.dox b/Core/Documentation/Doxygen/Groups/ModuleVisualizationNavigationControl.dox similarity index 87% rename from Documentation/Doxygen/Modules/ModuleVisualizationNavigationControl.dox rename to Core/Documentation/Doxygen/Groups/ModuleVisualizationNavigationControl.dox index 8543bfbee3..5e6a5b828a 100644 --- a/Documentation/Doxygen/Modules/ModuleVisualizationNavigationControl.dox +++ b/Core/Documentation/Doxygen/Groups/ModuleVisualizationNavigationControl.dox @@ -1,15 +1,15 @@ /** \defgroup NavigationControl Navigation Control Classes \ingroup Visualization -\brief The classes in this category tell the render (subclass of mitk::BaseRenderer) which +\brief The classes in this category tell the render (subclass of mitk::BaseRenderer) which slice (subclass mitk::SliceNavigationController) or from which direction (subclass mitk::CameraController) it has to render. -Contains two Stepper for stepping through the slices or through different camera views (e.g., +Contains two Stepper for stepping through the slices or through different camera views (e.g., for the creation of a movie around the data), respectively, and through time, if there is 3D+t data. */ \ No newline at end of file diff --git a/Documentation/Doxygen/Modules/ModuleVisualizationRenderer.dox b/Core/Documentation/Doxygen/Groups/ModuleVisualizationRenderer.dox similarity index 99% rename from Documentation/Doxygen/Modules/ModuleVisualizationRenderer.dox rename to Core/Documentation/Doxygen/Groups/ModuleVisualizationRenderer.dox index ade1036bad..e1e2428197 100644 --- a/Documentation/Doxygen/Modules/ModuleVisualizationRenderer.dox +++ b/Core/Documentation/Doxygen/Groups/ModuleVisualizationRenderer.dox @@ -1,42 +1,42 @@ /** \defgroup Renderer Renderer and RenderWindow Classes \ingroup Visualization \brief The MITK rendering model resembles the mechisms found in VTK. This section describes the core components for coordinating rendering processes and render windows. \section overviewVisualizationRenderer Overview To visualize a dataset it needs to be stored in the DataTree. Depending on the application, the whole DataTree may be displayed, or merely parts of it. The rendering of individual data items (e.g. volumes or polygon models) is conducted by specific Mappers: each kind of visualizable data has its own corresponding Mapper implementation (see \ref Mapper). MITK is designed to intrinsically provide different views on data. For example, a volume dataset is volume rendered in a 3D view, and displayed slice-wise in a 2D view. A polygon model would be displayed as a contour in 2D (i.e., the intersection of the 3D model and the respective 2D plane). This principle applies to all kinds of data, thereby ensuring a consistent visual representation regardless of the view type. It is realized by providing Mappers for each combination of data type and view type. Every item of the DataTree is associated with a list of Mappers, each capable of rendering the data item in a specific view. RenderWindows represent the rendering target: an area of the user interface into which data is rendered. The actual rendering process is controlled by Renderers, specifically by mitkVtkPropRenderer, which is a concrete implementation BaseRenderer and iterates over the elements of the DataTree to render each using the associated Mapper. Eeach data item of the DataTree has Geometry objects attached to it which describe the geometry of the data (e.g. its bounding box, location, or spatial conversion hints). \section vtkVisualizationRenderer Encapsulating VTK Rendering Mechanisms As a framework, MITK aims at making use of the visualization capabilities of VTK as much as possible. For the application developer building on top of MITK, the way of how to utilize specific VTK features should be straightforward and familiar. Therefore, most of the MITK rendering components closely resemble or integrate corresponding VTK components. Just like VTK, MITK defines Renderers and Mappers. These classes do not derive from their VTK counterparts, but integrate them and have similar scopes of responsibility. While the VTK rendering mechanism is mainly focused on establishing a pipeline of rendering components (data, filters, mappers, and renderers), MITK has a central DataTree and provides convenient ways of rendering different items of the tree according to their type. Internally, the VTK rendering pipeline is used, though it is more hidden from the application developer who merely makes use of existing rendering capabilities. As of MITK 0.8, the class vtkMitkRenderProp (a derivation of vtkProp) represents the single prop object in the VTK rendering pipeline responsible for coordinating the rendering of all objects in MITK's DataTree. The advantage of this approach is that all rendering management is done in the usual VTK rendering pipeline style, while the control of how data is actually rendered is entirely on MITK side. For example, MITK Mapper classes may either use VTK classes for rendering (actors, properties, ...), or do their rendering entirely in OpenGL where appropriate (e.g. in 2D Mapper classes). For further details refer to the page \ref Rendering. \section renderingManagerVisualizationRenderer Controlling it All: RenderingManager On a higher level, all rendering in MITK is managed and supervised by the RenderingManager. Its main task is to provide a central instance where any part of the application can request a repaint of a particular RenderWindow. Thereby, requests can be issued from multiple independent subroutines at one time, and only result in one repainting call, rather than induce many unnecessary rendering passes. Another task is the supervision of ongoing rendering activities. For large datasets, high quality rendering might become very slow and thus impede smooth user interactions. To alleviate this, level-of-detail rendering and abort-mechanisms are introduced and controlled by the RenderingManager to achieve interactive frame rate and response times. Note that these features are not yet available but currently under development. The rendering process could be further simplified by making the DataTree automatically detect data changes that require the data to be re-drawn. The fundamentals for such a mechanism already exist but still for many modifications a repainting request has to be issued by the entity causing it. \section implementationManagerVisualizationRenderer Platform-Specific Implementation -MITK tries to integrate seamlessly into the normal VTK rendering pipeline. The whole MITK data(tree) is capsuled into one customized vtkProp, the so-called vtkMitkRenderProp which is then integrated into VTK pipeline. +MITK tries to integrate seamlessly into the normal VTK rendering pipeline. The whole MITK data(tree) is capsuled into one customized vtkProp, the so-called vtkMitkRenderProp which is then integrated into VTK pipeline. The VTK integration into GUI systems, like e.g. QT, is therefore equal to normal VTK usage. As an example, the MITK MainApp requires the QT-VTK widget (provided by VTK) for integration of renderWindows into GUI. Further information on this can be found in section "Related Pages" "Rendering in MITK by means of the QT-VTK widget". */ \ No newline at end of file diff --git a/Documentation/Doxygen/Modules/Modules.dox b/Core/Documentation/Doxygen/Groups/Modules.dox similarity index 69% rename from Documentation/Doxygen/Modules/Modules.dox rename to Core/Documentation/Doxygen/Groups/Modules.dox index 3185b1b870..8a1f055fd8 100644 --- a/Documentation/Doxygen/Modules/Modules.dox +++ b/Core/Documentation/Doxygen/Groups/Modules.dox @@ -1,129 +1,98 @@ /** - \defgroup Core Core Classes + \defgroup Core Core + \ingroup MITKModules - \brief This category includes classes of the MITK Core library. + \brief This category includes classes of the MITK Core module. + + The MITK Core module contains abstractions for common data types and their + geometries, I/O facilities for loading and saving data in various formats, + infrastructures for handling user interaction and undo/redo operations, + GUI toolkit independent visualization classes, and a generic service registry. + + In almost all cases, additional MITK modules will make use of classes contained + in the Core module. */ /** \defgroup Data Data Classes - \ingroup DataManagement + \ingroup Core \brief This subcategory includes the data classes, e.g., for images (mitk::Image), surfaces (mitk::Surface), vessel-trees (mitk::VesselTreeData), etc. Data access classes are only included, if there is no equivalent in itk (see \ref ProcessAndAdaptorClasses "Process and Adaptor Classes" below). */ /** \defgroup IO IO Classes - \ingroup DataManagement + \ingroup Core \brief This subcategory includes the IO classes to read or write data objects. */ /** \defgroup DataStorage Data Storage Classes - \ingroup DataManagement + \ingroup Core \brief This subcategory includes the classes to store and retrieve objects from the mitk::DataStorage */ /** \defgroup ProcessAdaptor Process and Adaptor Classes \ingroup Core - \anchor ProcessAndAdaptorClasses \brief This category includes process (algorithm) classes developed specifically for mitk and (mainly) adaptor classes for the integration of algorithms from other toolkits (currently vtk, itk). The itk adaptor classes are also useful for data access to mitk data objects. */ /** \defgroup Process Process Classes \ingroup ProcessAdaptor \brief This subcategory includes process (algorithm) classes developed specifically for mitk. */ /** \defgroup InteractionUndo Interaction and Undo Classes \ingroup Core \brief This category includes classes that support the developer to create software that allows the user to interact with the data. This includes complex interactions that have multiple states (e.g., moving a handle of an active contour vs changing its local elasicity) and a concept to realize an undo/redo-mechanism. A detailed description of the rationale for these classes can be found in \ref InteractionPage. */ /** \defgroup Interaction Interaction Classes \ingroup InteractionUndo \brief This subcategory includes interaction classes (subclasses of mitk::StateMachine) that change the data according to the input of the user. For undo-support, the change is done by sending an OperationEvent to the respective data object, which changes itself accordingly. A detailed description of the rationale for these classes can be found in \ref InteractionPage. */ /** \defgroup Undo Undo Classes \ingroup InteractionUndo \brief This subcategory includes the undo/redo-specific classes. For undo-support, the change is done by sending an OperationEvent to the respective data object, which changes itself accordingly. A detailed description of the rationale for these classes can be found in \ref InteractionPage. */ - -/** - \defgroup ToolManagerEtAl Classes related to the Segmentation plugin - - \brief A couple of classes related to the Segmentation plugin. See also - \ref QmitkSegmentationTechnicalPage -*/ - -/** - \defgroup Registration Registration - - \brief A couple of classes related to registration. -*/ - -/** - \defgroup RigidRegistration Classes related to rigid registration - \ingroup Registration - - \brief A couple of classes related to rigid registration. -*/ - -/** - \defgroup PointBasedRegistration Classes related to point based registration - \ingroup Registration - - \brief A couple of classes related to point based registration. -*/ - -/** - \defgroup MITKPlugins MITK Plugins - - \brief This group includes all MITK Plugins. -*/ - -/** - \defgroup MITKExamplePlugins MITK Example Plugins - - \brief This group includes all MITK example plugins demonstrating specific framework features. -*/ diff --git a/Documentation/CMakeLists.txt b/Documentation/CMakeLists.txt index 4ddb87ec92..ba8bb90405 100644 --- a/Documentation/CMakeLists.txt +++ b/Documentation/CMakeLists.txt @@ -1,186 +1,185 @@ -# +# # Variables: # MITK_DOXYGEN_OUTPUT_DIR: doxygen output directory (optional) # Compile source code snippets #add_subdirectory(Snippets) find_package(Doxygen) if(DOXYGEN_FOUND) # Different doxygen versions produce different significantly different behaviour in the MITK documentation # especially in regards to the MITK Qt assistant help files. For this reason we support only one version at a time set(supported_doxygen_version "1.8.0") if(CMAKE_VERSION VERSION_LESS "2.8.8") EXECUTE_PROCESS(COMMAND ${DOXYGEN_EXECUTABLE} "--version" OUTPUT_VARIABLE DOXYGEN_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) endif() if(NOT DOXYGEN_VERSION VERSION_EQUAL ${supported_doxygen_version}) MESSAGE("Unsupported doxygen version ${DOXYGEN_VERSION}. MITK documentation has been tested to work with doxygen ${supported_doxygen_version}") endif() option(USE_DOT "Use dot program for generating graphical class diagrams with doxygen, if available" ON) option(MITK_DOXYGEN_BUILD_ALWAYS "Always build the MITK documentation when building the default target" OFF) option(MITK_DOXYGEN_GENERATE_QCH_FILES "Use doxygen to generate Qt compressed help files for MITK docs" OFF) mark_as_advanced(USE_DOT MITK_DOXYGEN_BUILD_ALWAYS MITK_DOXYGEN_GENERATE_QCH_FILES) set(HAVE_DOT "NO") if(DOXYGEN_DOT_EXECUTABLE AND USE_DOT) set(HAVE_DOT "YES") endif() -set(MITK_DOXYGEN_OUTPUT_DIR ${PROJECT_BINARY_DIR}/Documentation/Doxygen CACHE PATH "Output directory for doxygen generated documentation." ) set(MITK_DOXYGEN_TAGFILE_NAME ${MITK_DOXYGEN_OUTPUT_DIR}/MITK.tag CACHE INTERNAL "MITK Doxygen tag file") # This is relative to the working directory of the doxygen command set(MITK_DOXYGEN_STYLESHEET mitk_doxygen.css) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${MITK_DOXYGEN_STYLESHEET} ${CMAKE_CURRENT_BINARY_DIR}/${MITK_DOXYGEN_STYLESHEET} @COPYONLY) # Create QCH files for MITK and external projects set(MITK_DOXYGEN_GENERATE_QHP "NO") if(MITK_DOXYGEN_GENERATE_QCH_FILES) - + find_program(QT_HELPGENERATOR_EXECUTABLE NAMES qhelpgenerator qhelpgenerator-qt4 qhelpgenerator4 PATHS ${QT_BINARY_DIR} DOC "The location of the the Qt help generator executable" NO_DEFAULT_PATH ) mark_as_advanced(QT_HELPGENERATOR_EXECUTABLE) - + if(NOT QT_HELPGENERATOR_EXECUTABLE) message(SEND_ERROR "The Qt help generator could not be found. Disabling qch generation") else() set(MITK_DOXYGEN_GENERATE_QHP "YES") endif() # The name of the generated MITK qch file, relative to the # Doxygen HTML output folder set(MITK_DOXYGEN_QCH_FILE "${MITK_BINARY_DIR}/MITK-${MITK_REVISION_ID}.qch") # Generating ITK and VTK docs it not done yet #option(MITK_DOXYGEN_GENERATE_VTK_QCH_FILE "Use doxygen to generate a Qt compressed help file for VTK docs" OFF) #option(MITK_DOXYGEN_GENERATE_ITK_QCH_FILE "Use doxygen to generate a Qt compressed help file for ITK docs" OFF) #mark_as_advanced(MITK_DOXYGEN_GENERATE_VTK_QCH_FILE MITK_DOXYGEN_GENERATE_ITK_QCH_FILE) endif() if(MITK_USE_BLUEBERRY) file(RELATIVE_PATH _blueberry_doxygen_path ${MITK_DOXYGEN_OUTPUT_DIR}/html ${BLUEBERRY_DOXYGEN_OUTPUT_DIR}/html) set(BLUEBERRY_DOXYGEN_TAGFILE "${BLUEBERRY_DOXYGEN_TAGFILE_NAME}=${_blueberry_doxygen_path}") set(BLUEBERRY_DOXYGEN_LINK "BlueBerry Documentation") set(MITK_XP_LINK "\\ref mitkExtPointsIndex") configure_file(schema.css ${MITK_DOXYGEN_OUTPUT_DIR}/html/schema.css) - + set(MITK_DOXYGEN_ENABLED_SECTIONS "${MITK_DOXYGEN_ENABLED_SECTIONS} BLUEBERRY") endif(MITK_USE_BLUEBERRY) # Compile a doxygen input filter for processing CMake scripts include(mitkFunctionCMakeDoxygenFilterCompile) mitkFunctionCMakeDoxygenFilterCompile(NAMESPACE "CMake") # Configure some doxygen options if(NOT MITK_DOXYGEN_INTERNAL_DOCS) set(MITK_DOXYGEN_INTERNAL_DOCS "NO") set(MITK_DOXYGEN_HIDE_FRIEND_COMPOUNDS "YES") set(MITK_DOXYGEN_EXCLUDE_PATTERNS "*_p.* *Private.h */internal/*") else() set(MITK_DOXYGEN_HIDE_FRIEND_COMPOUNDS "NO") set(MITK_DOXYGEN_EXCLUDE_PATTERNS "") endif() if(NOT MITK_DOXYGEN_GENERATE_TODOLIST) set(MITK_DOXYGEN_GENERATE_TODOLIST "NO") endif() if(NOT MITK_DOXYGEN_GENERATE_BUGLIST) set(MITK_DOXYGEN_GENERATE_BUGLIST "NO") endif() if(NOT MITK_DOXYGEN_HTML_DYNAMIC_SECTIONS) set(MITK_DOXYGEN_HTML_DYNAMIC_SECTIONS "NO") endif() if(NOT MITK_DOXYGEN_UML_LOOK) set(MITK_DOXYGEN_UML_LOOK "NO") endif() if(NOT MITK_DOXYGEN_GENERATE_DEPRECATEDLIST) set(MITK_DOXYGEN_GENERATE_DEPRECATEDLIST "YES") endif() if(NOT DEFINED MITK_DOXYGEN_DOT_NUM_THREADS) set(MITK_DOXYGEN_DOT_NUM_THREADS 0) endif() configure_file(Doxygen/MainPage.dox.in ${CMAKE_CURRENT_BINARY_DIR}/Doxygen/MainPage.dox) configure_file(doxygen.conf.in ${CMAKE_CURRENT_BINARY_DIR}/doxygen.conf) if(MITK_DOXYGEN_BUILD_ALWAYS) set(_doc_in_all "ALL") else() set(_doc_in_all "") endif() add_custom_target(doc ${_doc_in_all} ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.conf WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) -if(MITK_USE_BLUEBERRY) +if(MITK_USE_BLUEBERRY) # convert the extension points schema files into html find_package(Ant) if(ANT_FOUND AND BLUEBERRY_DOC_TOOLS_DIR) list(APPEND MITK_XP_GLOB_EXPRESSIONS ${MITK_SOURCE_DIR}/Plugins/plugin.xml) file(GLOB_RECURSE _plugin_xmls ${MITK_XP_GLOB_EXPRESSIONS}) - - MACRO_CONVERT_SCHEMA(INPUT ${_plugin_xmls} + + MACRO_CONVERT_SCHEMA(INPUT ${_plugin_xmls} OUTPUT_DIR "${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html" TARGET_NAME mitkXPDoc ) - add_dependencies(doc mitkXPDoc) - if(${PROJECT_NAME} STREQUAL "MITK") - add_dependencies(doc BlueBerryDoc) - endif() + add_dependencies(doc mitkXPDoc BlueBerryXPDoc) + #if(${PROJECT_NAME} STREQUAL "MITK") + # add_dependencies(doc BlueBerryDoc) + #endif() endif(ANT_FOUND AND BLUEBERRY_DOC_TOOLS_DIR) endif(MITK_USE_BLUEBERRY) #if(MITK_DOXYGEN_GENERATE_ITK_QCH_FILE) # # add the command to generate the ITK documantation # add_custom_target(doc-itk # COMMAND ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.itk.conf) # add_dependencies(doc doc-itk) #endif() #if(MITK_DOXYGEN_GENERATE_VTK_QCH_FILE) # # add the command to generate the VTK documantation # add_custom_target(doc-vtk # COMMAND ${DOXYGEN} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.vtk.conf) # add_dependencies(doc doc-vtk) #endif() else(DOXYGEN_FOUND) -# copy blank documentation page to prevent QtHelp from being shown +# copy blank documentation page to prevent QtHelp from being shown # copy the .qhc and .qch files to $MITK_BIN/mitk/bin/ExtBundles/resources/ configure_file(pregenerated/MITKBlankPage.qch ${MITK_BINARY_DIR}/bin/ExtBundles/org.mitk.gui.qt.extapplication/resources/MITKBlankPage.qch COPYONLY) configure_file(pregenerated/MitkExtQtHelpCollection.qhc ${MITK_BINARY_DIR}/bin/ExtBundles/org.mitk.gui.qt.extapplication/resources/MitkExtQtHelpCollection.qhc COPYONLY) endif(DOXYGEN_FOUND) diff --git a/Documentation/Doxygen/API/Groups/Modules.dox b/Documentation/Doxygen/API/Groups/Modules.dox new file mode 100644 index 0000000000..7303dff8a3 --- /dev/null +++ b/Documentation/Doxygen/API/Groups/Modules.dox @@ -0,0 +1,24 @@ +/** + \defgroup ToolManagerEtAl Classes related to the Segmentation plugin + + \brief A couple of classes related to the Segmentation plugin. See also + \ref QmitkSegmentationTechnicalPage +*/ + +/** + \defgroup MITKModules MITK Modules + + \brief This group includes all MITK Modules. +*/ + +/** + \defgroup MITKPlugins MITK Plugins + + \brief This group includes all MITK Plugins. +*/ + +/** + \defgroup MITKExamplePlugins MITK Example Plugins + + \brief This group includes all MITK example plugins demonstrating specific framework features. +*/ diff --git a/Documentation/Doxygen/BlueBerry/BlueBerryExampleLauncherDialog.png b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryExampleLauncherDialog.png similarity index 100% rename from Documentation/Doxygen/BlueBerry/BlueBerryExampleLauncherDialog.png rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryExampleLauncherDialog.png diff --git a/Documentation/Doxygen/BlueBerry/BlueBerryExamples.dox b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryExamples.dox similarity index 100% rename from Documentation/Doxygen/BlueBerry/BlueBerryExamples.dox rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryExamples.dox diff --git a/Documentation/Doxygen/BlueBerry/BlueBerryExtensionPointsIntro.dox b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryExtensionPointsIntro.dox similarity index 100% rename from Documentation/Doxygen/BlueBerry/BlueBerryExtensionPointsIntro.dox rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryExtensionPointsIntro.dox diff --git a/Documentation/Doxygen/BlueBerry/BlueBerryIntro.dox b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryIntro.dox similarity index 93% rename from Documentation/Doxygen/BlueBerry/BlueBerryIntro.dox rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryIntro.dox index a7045f61e1..06e657920c 100644 --- a/Documentation/Doxygen/BlueBerry/BlueBerryIntro.dox +++ b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerryIntro.dox @@ -1,73 +1,79 @@ /** \page BlueBerryIntro BlueBerry Application Framework BlueBerry is an application framework used in MITK for creating modular and extensible end-user applications. More high-level documentation can be found below: - \subpage BlueBerryWorkbench +- \ref BlueBerryExamples -Please see the \ref BlueBerryExamples for code examples demonstrating different features of the appication framework. +Please see the \ref BlueBerryExamples for code examples demonstrating different features of the application framework. + +The BlueBerry developer reference is available here: + +- \ref BlueBerryPlugins +- \subpage BlueBerryExtPointsIndex \page BlueBerryWorkbench The Workbench: What are Views, Editors, Perspectives? BlueBerry makes use of the Eclipse UI guidlines which state some concepts on how to build up a GUI. The different objects of the platform UI shall be described here: \section Workbench Workbench \li root object of the platform UI \li collection of \ref WorkbenchWindow "windows" \image html workbench.jpg "The Workbech" \section WorkbenchWindow WorkbenchWindow \li has one \ref Workbench-Page "page" \image html workbench-window.jpg "Worbench Windows" \section WorkbenchPage Workbench Page \li denotes to the inner part of the \ref WorkbenchWindow "window", that is: everything except the title bar \li may have one menu bar, one toolbar, one shortcut bar, and one statusbar \li has one or more \ref Perspective "perspectives" \image html workbench-page.jpg "Workbench Page" \section Perspective Perspective
  • A visual container for a set of \ref Views "views" and content \ref Editors "editors"
  • Shows \ref Views "views" and \ref Editors "editors" in a certain layout
  • Like a page within a book:
    • Only one perspective is visible at any time
    • There are several perspectives inside a \ref Workbench-Page "page"
\image html workbench-window-perspective.png "A Perspective" \section Part Part \li every \ref Views "View" or \ref Editors "Editor" is called \b Part \subsection Editors Editors \li the StdMultiWidget is an example for an editor in our MainApp \li Contains the primary content, such as a document or image data, which users interact with \li content is the primary focus of attention and a reflection of the primary task \li primary position in the UI \li contributes commands to the workbench's main menu bar and toolbar \li shared in other perspectives \image html workbench-window-editor-area.png "Editor Area" \subsection Views Views
  • support the primary task
    • navigate a hierarchy of information
    • open an \ref Editors "editor"
    • view/edit properties
  • The views exist wholly within the perspective (not shared, one instance at a time)
  • Every functionality is a view- it supports medical image processing
\image html workbench-window-views.png "Views" \section ClassDiagram Summary as class diagram \image html workbench-class-diagram.jpg "class diagram" */ diff --git a/Documentation/Doxygen/BlueBerry/BlueBerrySelectionServiceIntro.dox b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerrySelectionServiceIntro.dox similarity index 100% rename from Documentation/Doxygen/BlueBerry/BlueBerrySelectionServiceIntro.dox rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/BlueBerrySelectionServiceIntro.dox diff --git a/Documentation/Doxygen/BlueBerry/ExtensionPointEx.png b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/ExtensionPointEx.png similarity index 100% rename from Documentation/Doxygen/BlueBerry/ExtensionPointEx.png rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/ExtensionPointEx.png diff --git a/Documentation/Doxygen/BlueBerry/ExtensionPoints.png b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/ExtensionPoints.png similarity index 100% rename from Documentation/Doxygen/BlueBerry/ExtensionPoints.png rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/ExtensionPoints.png diff --git a/Documentation/Doxygen/BlueBerry/MitkSelectionService.png b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/MitkSelectionService.png similarity index 100% rename from Documentation/Doxygen/BlueBerry/MitkSelectionService.png rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/MitkSelectionService.png diff --git a/Documentation/Doxygen/BlueBerry/SelectionServiceDiagram.png b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/SelectionServiceDiagram.png similarity index 100% rename from Documentation/Doxygen/BlueBerry/SelectionServiceDiagram.png rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/SelectionServiceDiagram.png diff --git a/Documentation/Doxygen/BlueBerry/SelectionServiceDiagram.xcf b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/SelectionServiceDiagram.xcf similarity index 100% rename from Documentation/Doxygen/BlueBerry/SelectionServiceDiagram.xcf rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/SelectionServiceDiagram.xcf diff --git a/Documentation/Doxygen/BlueBerry/application-window.jpg b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/application-window.jpg similarity index 100% rename from Documentation/Doxygen/BlueBerry/application-window.jpg rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/application-window.jpg diff --git a/Documentation/Doxygen/BlueBerry/workbench-class-diagram.jpg b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-class-diagram.jpg similarity index 100% rename from Documentation/Doxygen/BlueBerry/workbench-class-diagram.jpg rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-class-diagram.jpg diff --git a/Documentation/Doxygen/BlueBerry/workbench-page.jpg b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-page.jpg similarity index 100% rename from Documentation/Doxygen/BlueBerry/workbench-page.jpg rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-page.jpg diff --git a/Documentation/Doxygen/BlueBerry/workbench-window-editor-area.png b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-editor-area.png similarity index 100% rename from Documentation/Doxygen/BlueBerry/workbench-window-editor-area.png rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-editor-area.png diff --git a/Documentation/Doxygen/BlueBerry/workbench-window-editor-area.xcf b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-editor-area.xcf similarity index 100% rename from Documentation/Doxygen/BlueBerry/workbench-window-editor-area.xcf rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-editor-area.xcf diff --git a/Documentation/Doxygen/BlueBerry/workbench-window-perspective.png b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-perspective.png similarity index 100% rename from Documentation/Doxygen/BlueBerry/workbench-window-perspective.png rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-perspective.png diff --git a/Documentation/Doxygen/BlueBerry/workbench-window-perspective.xcf b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-perspective.xcf similarity index 100% rename from Documentation/Doxygen/BlueBerry/workbench-window-perspective.xcf rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-perspective.xcf diff --git a/Documentation/Doxygen/BlueBerry/workbench-window-views.png b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-views.png similarity index 100% rename from Documentation/Doxygen/BlueBerry/workbench-window-views.png rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-views.png diff --git a/Documentation/Doxygen/BlueBerry/workbench-window-views.xcf b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-views.xcf similarity index 100% rename from Documentation/Doxygen/BlueBerry/workbench-window-views.xcf rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window-views.xcf diff --git a/Documentation/Doxygen/BlueBerry/workbench-window.jpg b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window.jpg similarity index 100% rename from Documentation/Doxygen/BlueBerry/workbench-window.jpg rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench-window.jpg diff --git a/Documentation/Doxygen/BlueBerry/workbench.jpg b/Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench.jpg similarity index 100% rename from Documentation/Doxygen/BlueBerry/workbench.jpg rename to Documentation/Doxygen/DeveloperManual/Application/BlueBerry/workbench.jpg diff --git a/Documentation/Doxygen/DeveloperManual/Deployment.dox b/Documentation/Doxygen/DeveloperManual/Application/Deployment.dox similarity index 98% rename from Documentation/Doxygen/DeveloperManual/Deployment.dox rename to Documentation/Doxygen/DeveloperManual/Application/Deployment.dox index ea81e022c7..71408502a3 100644 --- a/Documentation/Doxygen/DeveloperManual/Deployment.dox +++ b/Documentation/Doxygen/DeveloperManual/Application/Deployment.dox @@ -1,46 +1,46 @@ /** -\page DeploymentPage Deployment +\page DeploymentPage Deploying MITK \section DeploymentPageIntroduction Introduction
  • easily create portable or installable versions of your MITK-based applications.
  • created packages include all MITK and 3rd party libraries necessary for running the application on other systems
  • distribute your binary application to other people without giving them your source code or putting them in the need for setting up a development environment themselves, eg for evaluation of your tool.
\note This does not install the MITK headers (like an SDK). If you want to develop applications based on MITK you still have to compile MITK yourself. \section DeploymentPagePlatform Platform specific notes \subsection DeploymentPagePlatformLinux Linux You can create a tarball (.tar.gz) of your MITK application which includes all necessary non-system libraries by following these steps:
  • Set the %CMake Variable CMAKE_BUILD_TYPE to either "Debug" or "Release". Any other type (or leaving the variable empty) will not work.
  • If you are using third-pary libraries not shipped with MITK, you might need to add the paths to the third-party libs to your LD_LIBRARY_PATH environment variable (not necessary if you use RPATH in your shared libraries).
  • Type "make package" in your build-tree. This will create a tarball in your build-tree directory.
\note Libraries in system locations (/lib/, /lib32/, /lib64/, /usr/lib/, /usr/lib32/,/usr/lib64/, and /usr/X11R6/) will not be included in the tarball. If you want to distribute Qt (for example), you have to do a custom Qt installation outside of these directories. \subsection DeploymentPagePlatformWindows Windows You can create a Zip file (.zip) or an NSIS installer (needs an installation of NSIS) for Windows platforms. Only "Release" builds are supported during packaging, the results of trying to package "Debug" builds are undefined. \note Building installers based on MinGW is not supported.
  • In Visual Studio, build the "PACKAGE" project, this will create a .zip file and a .exe NSIS installer (if NSIS is installed).
On some systems, it might still be necessary to install the Microsoft Visual C++ Redistributable Package to start the installed application successfully. \subsection DeploymentPagePlatformMacOS MacOS You can create a drag'n drop disk image (.dmg) file for MacOS. The procedure is pretty much the same as for Linux. \note On MacOS, libraries in system locations as pointed out in the Linux section \b and libraries located in /System/Library will not be copied. If you want to distribute any libraries from these locations, you have to install them somewhere else prior to configuring your MITK build. */ \ No newline at end of file diff --git a/Documentation/Doxygen/DeveloperManual/Application/DevelopmentApplication.dox b/Documentation/Doxygen/DeveloperManual/Application/DevelopmentApplication.dox new file mode 100644 index 0000000000..4e00e090fc --- /dev/null +++ b/Documentation/Doxygen/DeveloperManual/Application/DevelopmentApplication.dox @@ -0,0 +1,17 @@ +/** + +\page DevelopmentApplication Developing with the MITK Application Framework + +MITK offers a powerful application featuring a plugin system and many predefined plugins. You can configure this application to offer a set of functionality to the user and easily create an installer. +Working with the application, you will have to learn about extension points and the Blueberry framework itself. If you are new to the matter, please also consult \ref Architecture and \ref FirstSteps. + +
    +
  • \subpage BlueBerryIntro
  • +
  • \subpage BlueBerryExamples
  • +
+ +The MITK application extension-point reference is available here: + + - \subpage mitkExtPointsIndex + +*/ diff --git a/Core/Documentation/Doxygen/extension-points/mitkExtPointsIndex.dox b/Documentation/Doxygen/DeveloperManual/Application/ExtensionPointReference.dox similarity index 100% rename from Core/Documentation/Doxygen/extension-points/mitkExtPointsIndex.dox rename to Documentation/Doxygen/DeveloperManual/Application/ExtensionPointReference.dox diff --git a/Documentation/Doxygen/DeveloperManual/DeveloperManualPortal.dox b/Documentation/Doxygen/DeveloperManual/DeveloperManualPortal.dox new file mode 100644 index 0000000000..aa9276cf30 --- /dev/null +++ b/Documentation/Doxygen/DeveloperManual/DeveloperManualPortal.dox @@ -0,0 +1,31 @@ +/** +\page DeveloperManualPortal MITK: Developer Manual + +Development with MITK can happen under several disctinct conditions. Depending on whether you are using the Toolkit or the entire application, different sections may apply to you. In case you are unsure about what you need, please refer to \link Architecture The Architecture of MITK text\endlink. An extensive Introduction to MITK is available under \link StartingDevelopment Starting your MITK Development\endlink. + +Depending on whether you are working with the \link DevelopmentToolkit Toolkit\endlink or the \link DevelopmentApplication Application\endlink, you can refer to their respective pages. Generated API-Documentation can be found \link DevelopmentAPI here\endlink. + +\section DeveloperManualStarting Starting your MITK Development + +
    +
  • \subpage StartingDevelopment
  • +
      +
    • \ref Architecture
    • +
    • \ref SettingUpMITK
    • +
    • \ref GettingToKnowMITK
    • +
    • \ref FirstSteps
    • +
    • \ref AboutTestingPage
    • +
    +
  • \subpage DevelopmentToolkit
  • +
      +
    • \ref Concepts
    • +
    • \ref MITKModuleManualsListPage
    • +
    +
  • \subpage DevelopmentApplication
  • +
      +
    • \ref mitkExtPointsIndex
    • +
    +
  • \subpage DeploymentPage
  • +
+ +*/ diff --git a/Documentation/Doxygen/DeveloperManual/Development.dox b/Documentation/Doxygen/DeveloperManual/Development.dox deleted file mode 100644 index 5e1997f33c..0000000000 --- a/Documentation/Doxygen/DeveloperManual/Development.dox +++ /dev/null @@ -1,50 +0,0 @@ -/** -\page Development Development with MITK - -The following items are concerned with the practical use of the MITK library for software development. - -Some abstract concepts of MITK are described in \ref Concepts - -\section DevelopmentSetup Setting Up MITK - -\li \subpage SupportedPlatformsPage -\li \subpage BuildInstructionsPage -\li \subpage thirdpartylibs -\li \ref HowToNewProject - -\section DevelopmentGettingToKnow Getting To Know MITK - -\li \subpage DirectoryStructurePage -\li \subpage TutorialPage - -\section DevelopmentWith Developing With MITK - -\li \subpage CMAKE_FAQ -\li \subpage DICOMTesting -\li \subpage NewPluginPage -\li \subpage StatemachineEditor -\li \subpage mitkExtPointsIndex -\li \subpage DeploymentPage -\li \subpage KnownProblemsPage - -\section DevelopmentContributing Contributing To MITK - -\li \subpage DocumentationGuide -\li \subpage StyleGuideAndNotesPage - -\section DevelopmentGettingToKnowBlueberry Getting To Know BlueBerry - -\li \subpage BlueBerryExamples - -\section DevelopmentFurtherInfo Further Information - -This section lists some ressources you might want to look at if you could not find what you need in -the \ref Development or \ref Concepts sections. - -We hold regular internal seminars which may or may not have something to do with MITK directly. The slides can be found -here. - -If you have some problems with MITK you might want to take a look at the FAQ. - -If the above does not prove sufficient you can contact the Mailinglist. -*/ diff --git a/Documentation/Doxygen/DeveloperManual/Starting/AboutTesting/AboutTestingPage.dox b/Documentation/Doxygen/DeveloperManual/Starting/AboutTesting/AboutTestingPage.dox new file mode 100644 index 0000000000..a0231fc98d --- /dev/null +++ b/Documentation/Doxygen/DeveloperManual/Starting/AboutTesting/AboutTestingPage.dox @@ -0,0 +1,9 @@ +/** +\page AboutTestingPage Testing + +TODO +\subpage GeneralTests +\subpage RenderingTests +\subpage DICOMTesting + +*/ diff --git a/Core/Documentation/Doxygen/Concepts/Overview.dox b/Documentation/Doxygen/DeveloperManual/Starting/Architecture.dox similarity index 96% rename from Core/Documentation/Doxygen/Concepts/Overview.dox rename to Documentation/Doxygen/DeveloperManual/Starting/Architecture.dox index f5def8bb90..c1553fe018 100644 --- a/Core/Documentation/Doxygen/Concepts/Overview.dox +++ b/Documentation/Doxygen/DeveloperManual/Starting/Architecture.dox @@ -1,47 +1,47 @@ /** -\page OverviewPage Introduction: Overview on the Medical Imaging Interaction Toolkit (MITK) +\page Architecture The Architecture of MITK MITK is an open source software toolkit for medical image processing, subsequent data analysis and integration of medical hardware. It is designed with the aim of providing a modular and heavily reusable code base to enable rapid development of new features. Following this design philosophy MITK includes many different specialized modules e.g. the Segmentation Module. This document is aimed at giving an overview of the general structure of MITK. Furthermore it will give an introduction into the coding and design concepts behind this toolkit. \section OverviewPage_DesignOverview Design Overview MITK is designed to be used as a pure software library or as a complete application framework. Thus, a user of MITK can decide if he simply wants to add a new plug-in to the existing application framework or if he needs to implement his own application and wants to use MITK as a software library. Depending on the type of use MITK uses different software libraries, which is shown in the next figure for overview. \image html MitkOverview.png "Overview of MITK" Like shown above, MITK uses the following libraries. These are the main libraries MITK is based on. For further functionality you can optionally include others, a list can be found \ref thirdpartylibs "here" . Based on these libraries, MITK includes the following features:
  • High level interactions with data.
  • Specialized medical imaging algorithms (e.g. segmentation)
  • Support of 3D + t data.
  • Complete application framework, expandable by plug-ins
  • Standard tools for medical imaging as default plug-ins (e.g. measurement, segmentation)
  • Many specialized module for different topics on medical imaging (e.g. diffusion imaging, image guided therapy, live image/ultrasound data processing)
*/ diff --git a/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/FirstSteps.dox b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/FirstSteps.dox new file mode 100644 index 0000000000..72d5728de0 --- /dev/null +++ b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/FirstSteps.dox @@ -0,0 +1,13 @@ +/** +\page FirstSteps First steps in Development + +TODO + +
    +
  • \subpage NewPluginPage
  • +
  • \subpage NewModulePage
  • +
  • \subpage CMAKE_FAQ
  • +
  • \subpage StatemachineEditor
  • +
+ +*/ diff --git a/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/NewModule.dox b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/NewModule.dox new file mode 100644 index 0000000000..ac64bbafbe --- /dev/null +++ b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/NewModule.dox @@ -0,0 +1,4 @@ +/** +\page NewModulePage How to create a new MITK Module + +*/ diff --git a/Documentation/Doxygen/DeveloperManual/NewPlugin.dox b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/NewPlugin.dox similarity index 100% rename from Documentation/Doxygen/DeveloperManual/NewPlugin.dox rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/NewPlugin.dox diff --git a/Documentation/Doxygen/StatemachineEditor/StatemachineEditor.dox b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/StatemachineEditor.dox similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/StatemachineEditor.dox rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/StatemachineEditor.dox diff --git a/Documentation/Doxygen/StatemachineEditor/images/BuildPath.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/BuildPath.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/BuildPath.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/BuildPath.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/CreateJavaProject.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/CreateJavaProject.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/CreateJavaProject.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/CreateJavaProject.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/Import.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/Import.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/Import.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/Import.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/Import2.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/Import2.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/Import2.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/Import2.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/Import3.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/Import3.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/Import3.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/Import3.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/Import4.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/Import4.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/Import4.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/Import4.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/NewStatemachine.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/NewStatemachine.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/NewStatemachine.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/NewStatemachine.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/NewStatemachine1.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/NewStatemachine1.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/NewStatemachine1.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/NewStatemachine1.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/NewStatemachine2.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/NewStatemachine2.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/NewStatemachine2.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/NewStatemachine2.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/NewStatemachine3.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/NewStatemachine3.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/NewStatemachine3.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/NewStatemachine3.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/Runas.png b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/Runas.png similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/Runas.png rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/Runas.png diff --git a/Documentation/Doxygen/StatemachineEditor/images/addAction.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/addAction.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/addAction.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/addAction.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/application.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/application.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/application.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/application.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/application1.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/application1.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/application1.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/application1.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/changeEvent.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/changeEvent.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/changeEvent.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/changeEvent.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/openPropertiesView.PNG b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/openPropertiesView.PNG similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/openPropertiesView.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/openPropertiesView.PNG diff --git a/Documentation/Doxygen/StatemachineEditor/images/openstatemachinexml.png b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/openstatemachinexml.png similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/openstatemachinexml.png rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/openstatemachinexml.png diff --git a/Documentation/Doxygen/StatemachineEditor/images/specifycontainer.png b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/specifycontainer.png similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/specifycontainer.png rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/specifycontainer.png diff --git a/Documentation/Doxygen/StatemachineEditor/images/specifycontainer2.png b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/specifycontainer2.png similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/specifycontainer2.png rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/specifycontainer2.png diff --git a/Documentation/Doxygen/StatemachineEditor/images/specifycontainer3.png b/Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/specifycontainer3.png similarity index 100% rename from Documentation/Doxygen/StatemachineEditor/images/specifycontainer3.png rename to Documentation/Doxygen/DeveloperManual/Starting/FirstSteps/StatemachineEditor/images/specifycontainer3.png diff --git a/Documentation/Doxygen/DeveloperManual/CMakeFAQ.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/CMakeFAQ.dox similarity index 98% rename from Documentation/Doxygen/DeveloperManual/CMakeFAQ.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/CMakeFAQ.dox index 2486bfc14e..a0495ae8a6 100644 --- a/Documentation/Doxygen/DeveloperManual/CMakeFAQ.dox +++ b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/CMakeFAQ.dox @@ -1,38 +1,38 @@ /** -\page CMAKE_FAQ %CMake FAQ +\page CMAKE_FAQ CMake FAQ \section CMAKE_FAQ_General A general comment MITK uses %CMake for configuration. If you want to develop either using MITK as a toolkit or by extending the capabilities of the applications provided by us we recommend using %CMake for your own prject as well. While it might be possible to use MITK in conjunction with other options, such as QMake or setting up your own project manually it will invariably use a lot of work and probably hacks as well. As we have no experience in this we will not be able to help you, so be prepared to have to do a lot of tweaking on your own. This guide does not try to give a general introduction to Cmake, instead it tries to answer some basic questions that might arise for those new to %CMake, to help you get started on MITK. For a more comprehensive introduction on %CMake see here. We will assume in this guide, that the path to your source is /MITK/. \section CMAKE_FAQ_Question Basic Questions \subsection CMAKE_FAQ_Question_WhereGetIt Where do I get CMake and what version do I need? See \ref BuildInstructions_Prerequisites. \subsection CMAKE_FAQ_Question_NewPluginNothing I coded a new plugin for the Workbench and nothing happened. Why? The correct way to create a new plugin is described in \ref NewPluginOnly. Do note that you need to move the source to the MITK/Plugins directory and you will have to add the plugin to the config file (most likely MITK/Plugins/Plugins.cmake). After that see \ref CMAKE_FAQ_Question_HowDoIActivatePlugin. \subsection CMAKE_FAQ_Question_HowDoIActivatePlugin I want to use a plugin, how do I activate it?
  1. Start %CMake
  2. Configure
  3. Set the variable MITK_BUILD_ to TRUE
  4. Configure again
  5. Generate
  6. Start a build using your development environment
\subsection CMAKE_FAQ_Question_HowDoIActivateModule I want to use a module, how do I activate it? Modules are build automatically if a plugin that requires them is activated. See \ref CMAKE_FAQ_Question_HowDoIActivatePlugin. \subsection CMAKE_FAQ_Question_HowOwnToolkits MITK always downloads the toolkits, but I want to use my own. This is covered in \ref HowToNewProjectCustomizingMITKConfigure. \subsection CMAKE_FAQ_Question_HowOwnProjectMITK I want to use an MITK plugin in my own project but I can not find it. See \ref HowToNewProjectAddingMITKFunctionality. */ \ No newline at end of file diff --git a/Core/Documentation/Doxygen/Concepts/CodingGeneral.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Coding.dox similarity index 100% rename from Core/Documentation/Doxygen/Concepts/CodingGeneral.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Coding.dox diff --git a/Documentation/Doxygen/DeveloperManual/DirectoryStructure.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/DirectoryStructure.dox similarity index 100% rename from Documentation/Doxygen/DeveloperManual/DirectoryStructure.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/DirectoryStructure.dox diff --git a/Documentation/Doxygen/DeveloperManual/DocumentationExample.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/DocumentationExample.dox similarity index 100% rename from Documentation/Doxygen/DeveloperManual/DocumentationExample.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/DocumentationExample.dox diff --git a/Documentation/Doxygen/DeveloperManual/DocumentationGuide.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/DocumentationGuide.dox similarity index 100% rename from Documentation/Doxygen/DeveloperManual/DocumentationGuide.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/DocumentationGuide.dox diff --git a/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/GettingToKnowMITK.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/GettingToKnowMITK.dox new file mode 100644 index 0000000000..e418a0b301 --- /dev/null +++ b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/GettingToKnowMITK.dox @@ -0,0 +1,14 @@ +/** +\page GettingToKnowMITK Getting to know MITK + +TODO +
    +
  • \subpage DirectoryStructurePage
  • +
  • \subpage TutorialPage
  • +
  • \subpage CMAKE_FAQ
  • +
  • \subpage StyleGuideAndNotesPage
  • +
  • \subpage DocumentationGuide
  • +
  • \subpage CodingPage
  • +
  • \subpage KnownProblemsPage
  • +
+*/ diff --git a/Documentation/Doxygen/DeveloperManual/KnownProblems.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/KnownProblems.dox similarity index 100% rename from Documentation/Doxygen/DeveloperManual/KnownProblems.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/KnownProblems.dox diff --git a/Documentation/Doxygen/DeveloperManual/StyleGuideAndNotes.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/StyleGuideAndNotes.dox similarity index 100% rename from Documentation/Doxygen/DeveloperManual/StyleGuideAndNotes.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/StyleGuideAndNotes.dox diff --git a/Documentation/Doxygen/Modules/CMakeLists.txt b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/CMakeLists.txt similarity index 100% rename from Documentation/Doxygen/Modules/CMakeLists.txt rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/CMakeLists.txt diff --git a/Documentation/Doxygen/Tutorial/Step00.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step00.dox similarity index 100% rename from Documentation/Doxygen/Tutorial/Step00.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step00.dox diff --git a/Documentation/Doxygen/Tutorial/Step01.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step01.dox similarity index 100% rename from Documentation/Doxygen/Tutorial/Step01.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step01.dox diff --git a/Documentation/Doxygen/Tutorial/Step02.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step02.dox similarity index 100% rename from Documentation/Doxygen/Tutorial/Step02.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step02.dox diff --git a/Documentation/Doxygen/Tutorial/Step03.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step03.dox similarity index 100% rename from Documentation/Doxygen/Tutorial/Step03.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step03.dox diff --git a/Documentation/Doxygen/Tutorial/Step04.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step04.dox similarity index 100% rename from Documentation/Doxygen/Tutorial/Step04.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step04.dox diff --git a/Documentation/Doxygen/Tutorial/Step05.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step05.dox similarity index 100% rename from Documentation/Doxygen/Tutorial/Step05.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step05.dox diff --git a/Documentation/Doxygen/Tutorial/Step06.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step06.dox similarity index 100% rename from Documentation/Doxygen/Tutorial/Step06.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step06.dox diff --git a/Documentation/Doxygen/Tutorial/Step07.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step07.dox similarity index 100% rename from Documentation/Doxygen/Tutorial/Step07.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step07.dox diff --git a/Documentation/Doxygen/Tutorial/Step08.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step08.dox similarity index 100% rename from Documentation/Doxygen/Tutorial/Step08.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step08.dox diff --git a/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step09.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step09.dox new file mode 100644 index 0000000000..616b1d1cf0 --- /dev/null +++ b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step09.dox @@ -0,0 +1,78 @@ +/** + +\page Step09Page MITK Tutorial - Step 9: A plug-in + +MITK uses a very modular concept to maximize reusability and portability. A MITK application based on the BlueBerry +application framework (for example the MITK Workbench) consists of several bundles (or plug-ins). A bundle can contain +resources and program logic. It can also contribute so-called Views to the main application, which provide a specific +user interface for controlling the bundles functions. + +The creation of a MITK plug-in is considerably facilitated by using the MITK PluginGenerator as described in \ref NewPluginPage . + +The mentioned tool was used to create a plug-in called org.mitk.example.gui.regiongrowing. +Let's first look at what files the PluginGenerator created: + +\verbatim +documentation\doxygen\ + modules.dox......................... Doxygen file for documenting your plug-in + +resources\ + icon.xpm............................ The icon of your plug-in. GIMP or other programs (including your text editor) + can be used to change this + +src\internal\ + QmitkRegionGrowingView.cpp.......... The most important file, implementing behaviour + QmitkRegionGrowingView.h............ Header file of the functionality + QmitkRegionGrowingViewControls.ui... XML file of the Qt Designer, describes buttons, combo boxes, etc. of your controls + +CMakeLists.txt \...................... Build system related files for CMake +files.cmake / +manifest_headers.cmake................ Information about your plug-in +plugin.xml ........................... BlueBerry integration +\endverbatim + +If you are not familiar with Qt development, please look into +this Digia page describing .ui files (no, forget about the please, DO it!) + +The C++ files implement a subclass of QmitkAbstractView. In this special case of QmitkRegionGrowing, we added the ability to set some seed points and run a region grower. If you are interested in the concrete changes necessary to turn a freshly generated QmitkRegionGrowing into an integrated one: + +To add a mitk::PointSet for the seed points: +QmitkRegionGrowingView.h + +Add includes and forward declarations: +\snippet QmitkRegionGrowingView.h includes + +Add the point set and a pointer to a QmitkPointListWidget as a private member: +\snippet QmitkRegionGrowingView.h members + +QmitkRegionGrowingView.cpp + +CreateQtPartControl(): +\snippet QmitkRegionGrowingView.cpp cpp-createqtpartcontrol + +To use the ITK region grower: + +QmitkRegionGrowingView.h + +Add the private method: +\snippet QmitkRegionGrowingView.h itkimageprocessing + +QmitkRegionGrowingView.cpp + +Add includes: +\snippet QmitkRegionGrowingView.cpp cpp-includes + +DoImageProcessing(): +\snippet QmitkRegionGrowingView.cpp cpp-doimageprocessing + +And add the new method: +\snippet QmitkRegionGrowingView.cpp cpp-itkimageaccess + +Have fun using MITK! + +If you meet any difficulties during your first steps, don't hesitate to ask on the MITK mailing list mitk-users@lists.sourceforge.net! +People there are kind and will try to help you. + + \ref Step08Page "[Previous step]" \ref Step10Page "[Next Step]" \ref TutorialPage "[Main tutorial page]" + +*/ diff --git a/Documentation/Doxygen/Tutorial/Step10.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox similarity index 96% rename from Documentation/Doxygen/Tutorial/Step10.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox index 82ee944421..493da74bde 100644 --- a/Documentation/Doxygen/Tutorial/Step10.dox +++ b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Step10.dox @@ -1,432 +1,432 @@ /** \page Step10Page MITK Tutorial - Step 10: Adding new Interaction \tableofcontents \section HowToUseDataInteractor How to use an existing DataInteractor MITK provides finished DataInteractors for a variety of tasks, they can be found in Code/Core/Interactors. They can be used with state machine patterns and config files located under Resources/Interaction. A DataInteractor consists of four parts. The class describing the functionality and two XML files; one describes the state machine pattern, that is the workflow of an interaction and the second describes the user events which trigger an action. Lastly every DataInteractor works on a DataNode in which it stores and manipulates data. To use a DataInteractor these parts have to be brought together. This code demonstrates the use of an existing DataInteractor exemplary for the PointSetDataInteractor: First we need a DataNode that is added to the DataStorage. \code mitk::DataNode::Pointer dataNode = mitk::DataNode::New(); GetDataStorage()->Add(dataNode.GetPointer()); \endcode Then we create an instance of to PointSetDataInteractor and load a statemachine pattern as well as a configuration for it: \code m_CurrentInteractor = mitk::PointSetDataInteractor::New(); m_CurrentInteractor->LoadStateMachine("PointSet.xml"); m_CurrentInteractor->LoadEventConfig("PointSetConfig.xml"); \endcode Lastly the DataNode is added to the DataInteractor \code m_CurrentInteractor->SetDataNode(dataNode); \endcode now the DataInteractor is ready for usage. \section SectionImplementationDataInteractor How to implement a new DataInteractor This second part of the tutorial step goes beyond the activation of an interactor, that modifies data by user interaction) as shown above. It shows what needs to be implemented to add a new way of interaction within your MITK application. Please see \ref DataInteractionPage as an introduction to the MITK interaction mechanism, you may also want to read \ref DataInteractionTechnicalPage. This tutorial is structured as follows: The first section deals with config files, describing all the parameters of events and how to use them in a configuration file. In the second section the basics are described that are needed to write a state machine pattern. The last section deals with brining configuration, state machine pattern and code together and gives an examplary implementation of a DataInteractor. \section ConfigFileDescriptionSection How to create a Config-File \subsection EventDescriptionSection Event Description Events are described by their parameters. Each event type has its own set of parameters that can be set in the configuration file. If a parameter is ommitted it is set to its default value. Following all possible parameters are listed and described, to which parameters events have is decribed in their respective documentation. Mandatory for each event description is the event class and the event variant. The parameters of an event are set by attribute tags. \note Refer to \ref EventClassSection for the meaning of event class. \b Mouse \b Buttons \n mitk::MouseButtons represent the buttons. They can be used for two attributes. First the EventButton which describes the button that triggered the event, this allways is a single button. Secondly the ButtonState attribute that describes which buttons were pressed at the moment the event has been generated. For example assume the right mouse button and the middle mouse button are already pressed, now also the left mouse button is pressed too and generates a second event, this would be described as follows: \code \endcode Note: Technically the LeftMouseButton is also pressed and should be listed in the ButtonState, but this is taken care of by the mitk:EventFactory . Key Events \n mitk::InteractionKeyEvent represents a pressed key, which key is pressed is provided with the Key attribute like this \code \endcode or \code \endcode \note Key Events do not require an explicit configuration all, for all key events there exists a predefined event variant with the name 'Std' + value, that is key a is named 'StdA'. The names for special keys are listed here: \dontinclude mitkInteractionEventConst.h \skipline // Special Keys \until // End special keys Modifier Keys \n mitk::ModifierKeys represent the combination of pressed modifier keys, several modifier keys pressed at the same time are denoted by listing them all separated by commas. \code \endcode \b ScrollDirection \n This attribute is unique to the mitk::MouseWheelEvent and describes the direction in which the mouse wheel is rotated. In the event description actual only the direction is provided, but the event is generated with the actual value, and this value can be retrieved from the object. \code \endcode \subsection ExamplesSection Examples Examples for key events: \code - + - + - + - + \endcode Examples for MousePress events: \code - + - + - + - + \endcode There exists a standard configuration file for the most common events called GlobalConfig.xml that can be used to as a default and can be extended by a specific definition. \subsection ParameterDescriptionSection Parameter Description It is also possible to store parameters in the config file. Those are stored using the param-tag, like this: \code \endcode Within the application these properties can then be access via a mitk::PropertyList like this: \code // sm - state machine loaded with config file example2 mitk::PropertyList::Pointer properties = GetAttributes(); std::string prop1; properties->GetStringProperty("property1",prop1); \endcode \section HowToStateMachine HowTo Write a State Machine A state machine pattern is described in a XML file. \subsection StateSection States States are described using the state-tag. Each state has to have a name. Exactly one state has to be as start state in each state machine to indicate the state in which the state machine is set when it is constructed. So a valid, but rather useless state machine would like like this: \code \endcode Optionally a state can be assigned a special mode that influences the event distribution. These modes are GRAB_INPUT , PREFER_INPUT and REGULAR (where REGULAR is default and does not need to be indicated). See \ref DispatcherEventDistSection for a description of these modes. Use the special modes only when necessary as they prevent other DataInteractors to receive events. \code \endcode \subsection TransitionSection Transitions Transitions are part of a state and describe all possible state switches, and are therefore important for modelling an interaction scheme. Transitions consist a part that describes the event which triggers the transition (event class and event variant) and a target which is state to which the state machine switches after executing a transition. An event class describes the event type (see mitk::InteractionEvent for the different classes) and the event variant is a specification thereof and the exact description is taken from a config file. Together they determine which event can trigger this transition. For example this state machine will switch from state A to state B when the StdMousePressPrimaryButton event (left mouse button is pressed) occurs. \subsubsection EventClassSection Event Class The event class description supports the polymorphism of the event classes. Therefore state machine patters should be written in the most general ways possible. So for a given class hierarchy like this: \dot digraph { node [shape=record, fontname=Helvetica, fontsize=10]; a [ label="{PositionEvent}"]; b [ label="{MousePressEvent}" ]; c [ label="MouseReleaseEvent" ]; d [ label="TouchEvent", style=dotted ]; a -> b; a -> c; a -> d; } \enddot in the state machine pattern the PositionEvent can be declared as event class to restrict to the events which hold a position information. The actual implementation is then given in the configuration file. In this case it allows to define event of the classes PositionEvent itself, or MousePressEvent,MouseReleaseEvent,TouchEvent. This has the advantage that the patterns remain the same no matter what input devices are used, and the state machine patterns can be configured for newly added event classes as long as they match the class hierachy (this ensures they hold the neccessary properties). \code \endcode \subsection ActionSection Actions Actions can be added to transitions and represent functions in the DataInteractor that are executed on taking a transition. The following simple state machine will listen for left mouse clicks and execute two actions (and actually never stop). \code \endcode In order to tell the DataInteractor which function to execute these actions are made known to the DataInteractor using the CONNECT_FUNCTION macro. This example assumes that there exists an ExampleInteractor which inherits from DataInteractor. This class implements the functions AddPoint and CountClicks. The actions are introduced by implementing the virtual method ConnectActionsAndFunctions(): \code void mitk::ExampleInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("countClicks", CountClicks); } \endcode \section HowToDataInteractor Implementation a new DataInteractor DataInteractors are to inherit from mitk::DataInteractor. Their functionality is implemented in functions that follow this interface: \code bool SomeFunctionality(StateMachineAction* , InteractionEvent*); \endcode Your functions are connected with actions by implementing the function ConnectActionsAndFunctions(), e.g. \code void mitk::ExampleInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("enoughPoints", EnoughPoints); } \endcode Now all that is left it to write a state machine pattern and a config file as is described in the tutorials. \subsection ExampleInternalEvent PointSetDataInteractor To provide a useful example the mitk::PointSetDataInteractor is annotated with comments that describe the important parts for an implementation of a DataInteractor. This step assumes knowlege of the Interaction concept described in \ref DataInteractionPage and some background of the implementation which is described in \ref DataInteractionPageTechnical. Please refer to these pages before proceeding. DataInteractor are to inherit from mitk::DataInteractor. Their functionality is implemented in functions that follow this interface: \code bool SomeFunctionality(StateMachineAction* , InteractionEvent*); \endcode Your functions are connected with actions by implementing the function ConnectActionsAndFunctions(), e.g. \code void mitk::ExampleInteractor::ConnectActionsAndFunctions() { CONNECT_FUNCTION("addPoint", AddPoint); CONNECT_FUNCTION("enoughPoints", EnoughPoints); } \endcode Now all that is left it to write a state machine pattern and a config file as is described in the tutorials. \subsection ExampleInternalEvent Example Interactor using InternalEvent A useful tool in creating DataInteractors are mitk::InternalEvents which allow to the DataInteractor send signals on its own. The following will describe how to build a DataInteractor that allows to add points until a certain number of points is reached. The number of accepted points is provided in the config file as a parameter. So we start by writing a state machine pattern that add points until it receives an InternalEvent telling it, that enough points have been added. \code <--! dead state, nothing happens any more, once we reached this --> \endcode In our config file we set the number of maximal points to 10, and define AddPointClick as a right mouse click with the ctrl button pressed. \code - + - + \endcode The implementation is desribed in the following. \see Step10.h \see Step10.cpp \dontinclude Step10.h Implementation of protected functions: \skipline protected: \until virtual void ConfigurationChanged(); ConnectActionsAndFunctions - Is inherited from mitk::InteractionStateMachine, here action strings from the xml are connected with functions in the Interactor (as seen above). In our example this looks like this: \dontinclude Step10.cpp \skipline void mitk::ExampleInteractor::ConnectActionsAndFunctions() \until } - ConfigurationChanged - Is called whenever a new configuration file is loaded (by the mitk::EventHandler super class), + ConfigurationChanged - Is called whenever a new configuration file is loaded (by the mitk::InteractionEventHandler super class), this function allows to implement initialization code that depends on configuration values. In our example we want to set the limit of allowed points: \dontinclude Step10.cpp \skipline void mitk::ExampleInteractor::ConfigurationChang \until } Next the actual functionality of the DataInteractor is implemented, by providing one function per action, following this prototype: \code bool FUNCTION_NAME (StateMachineAction* , InteractionEvent*); \endcode \dontinclude Step10.h \skipline private: \until bool EnoughPoints(StateMac Each function has to return a boolean value. True if the action has been executed, and false if the action has not been executed. \dontinclude Step10.cpp \skipline bool mitk::ExampleInteractor::AddPoint(StateM \until //- Here we see an internal event used to signal that the point set reached the maximal number of allowed points. The event is created and added to the Dispatchers event queue. \dontinclude Step10.cpp \skipline // create internal \until positionEvent->GetSender( \note That internal events do not need any mapping to event variants. Their signal same is equivalent with the event variant. - There are also two documented classes implementing a DataInteractor and an EventObserver which can be looked at for further + There are also two documented classes implementing a DataInteractor and an InteractionEventObserver which can be looked at for further understanding: \see mitk::PointSetDataInteractor \see mitk::DisplayInteractor Have fun with creating your own interaction and please think about contributing it to MITK! If you meet any difficulties during this step, don't hesitate to ask on the MITK mailing list mitk-users@lists.sourceforge.net! People there are kind and will try to help you. \ref Step09Page "[Previous step]" \ref TutorialPage "[Main tutorial page]" */ \ No newline at end of file diff --git a/Documentation/Doxygen/Tutorial/Tutorial.dox b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Tutorial.dox similarity index 100% rename from Documentation/Doxygen/Tutorial/Tutorial.dox rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/Tutorial.dox diff --git a/Documentation/Doxygen/Tutorial/configureCMake.PNG b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/configureCMake.PNG similarity index 100% rename from Documentation/Doxygen/Tutorial/configureCMake.PNG rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/configureCMake.PNG diff --git a/Documentation/Doxygen/Tutorial/configureVisualStudioProperties.png b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/configureVisualStudioProperties.png similarity index 100% rename from Documentation/Doxygen/Tutorial/configureVisualStudioProperties.png rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/configureVisualStudioProperties.png diff --git a/Documentation/Doxygen/Tutorial/step10_result.png b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step10_result.png similarity index 100% rename from Documentation/Doxygen/Tutorial/step10_result.png rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step10_result.png diff --git a/Documentation/Doxygen/Tutorial/step1_result.png b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step1_result.png similarity index 100% rename from Documentation/Doxygen/Tutorial/step1_result.png rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step1_result.png diff --git a/Documentation/Doxygen/Tutorial/step2_result.png b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step2_result.png similarity index 100% rename from Documentation/Doxygen/Tutorial/step2_result.png rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step2_result.png diff --git a/Documentation/Doxygen/Tutorial/step3a_result.png b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step3a_result.png similarity index 100% rename from Documentation/Doxygen/Tutorial/step3a_result.png rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step3a_result.png diff --git a/Documentation/Doxygen/Tutorial/step3b_result.png b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step3b_result.png similarity index 100% rename from Documentation/Doxygen/Tutorial/step3b_result.png rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step3b_result.png diff --git a/Documentation/Doxygen/Tutorial/step4a_result.png b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step4a_result.png similarity index 100% rename from Documentation/Doxygen/Tutorial/step4a_result.png rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step4a_result.png diff --git a/Documentation/Doxygen/Tutorial/step4b_result.png b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step4b_result.png similarity index 100% rename from Documentation/Doxygen/Tutorial/step4b_result.png rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step4b_result.png diff --git a/Documentation/Doxygen/Tutorial/step5_result.png b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step5_result.png similarity index 100% rename from Documentation/Doxygen/Tutorial/step5_result.png rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step5_result.png diff --git a/Documentation/Doxygen/Tutorial/step6_result.png b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step6_result.png similarity index 100% rename from Documentation/Doxygen/Tutorial/step6_result.png rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step6_result.png diff --git a/Documentation/Doxygen/Tutorial/step8_result.png b/Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step8_result.png similarity index 100% rename from Documentation/Doxygen/Tutorial/step8_result.png rename to Documentation/Doxygen/DeveloperManual/Starting/GettingToKnow/Tutorial/step8_result.png diff --git a/Documentation/Doxygen/DeveloperManual/BuildInstructions.dox b/Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox similarity index 100% rename from Documentation/Doxygen/DeveloperManual/BuildInstructions.dox rename to Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox diff --git a/Documentation/Doxygen/DeveloperManual/BuildToolkits.dox b/Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/BuildToolkits.dox similarity index 100% rename from Documentation/Doxygen/DeveloperManual/BuildToolkits.dox rename to Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/BuildToolkits.dox diff --git a/Documentation/Doxygen/DeveloperManual/HowToNewProject-MyProjectLayout.png b/Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/HowToNewProject-MyProjectLayout.png similarity index 100% rename from Documentation/Doxygen/DeveloperManual/HowToNewProject-MyProjectLayout.png rename to Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/HowToNewProject-MyProjectLayout.png diff --git a/Documentation/Doxygen/DeveloperManual/HowToNewProject.dox b/Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/HowToNewProject.dox similarity index 99% rename from Documentation/Doxygen/DeveloperManual/HowToNewProject.dox rename to Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/HowToNewProject.dox index d961d9c9e4..f9b4cdeaa7 100644 --- a/Documentation/Doxygen/DeveloperManual/HowToNewProject.dox +++ b/Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/HowToNewProject.dox @@ -1,161 +1,161 @@ /** \page HowToNewProject Creating a new MITK project This page is intended to give a comprehensive guide to setting up your own MITK based project. It will use the application framework provided by MITK and is probably the preferred way for most users. The first part of this document is a tutorial aimed at newcomers to MITK and possibly %CMake and tries to give as much help as possible on setting up your own project. If you are looking for more technical information about customizing MITK, the structure of the superbuild or packaging you might want to read the \ref HowToNewProjectAdvancedInformation. If you have set up your MITK project already and want to start developing you could take a look at \ref TutorialPage. \section HowToNewProjectGettingStarted Getting Started To bootstrap your project MITK offers two convenient options:
  1. Use the MITK Plugin Generator, a command line tool used to generate a customized MITK project and/or MITK plug-ins (available for download here).
  2. Use the MITK project template as an example project.
Both options will provide you with a project which contains a "superbuild" mechanism to automatically download, configure, and build MITK as a dependency of your own project. The MITK Plugin Generator generates code using the supplied command line arguments, whereas the MITK project template needs immediate modifications to customize it to your naming schemes. However, the project template will potentially contain more code demonstrating features of MITK. \note Using the MITK Plugin Generator is recommended for beginners. \section HowToNewProjectPrerequisites Prerequisites What ever option you choose, a MITK-based project needs essentially the same prerequisites as MITK itself. Please see \ref BuildInstructions_Prerequisites for details. \note If you use one of the two options above you will \b not \b need to build MITK yourself. This will be done automatically. \section HowToNewProjectCreatingSourceDir Preparing your source directory In order to start developing with MITK, you first have to set up the source directory for your project. \subsection HowToNewProjectSourceUsingGenerator Using the MITK Plugin Generator The usage of the Plugin Generator for creating a new project is described in \ref NewPluginWithProject, please have a look there. \subsection HowToNewProjectSourceUsingTemplate Using the MITK Project Template Download the project as a tarball or zipball and extract it to your desired source directory. \note This is a \b template \b. You must modify it such that it fits the needs of your particular project. Especially you should do a global search and replace for the string "awesome" to rename the template application and plug-in. You may want to rename some files too. \section HowToNewProjectGeneratingCMake Generating your binary with CMake After you have set up your source directory you can proceed to generate your binary directory using %CMake. Depending on your operating system and preferences you might want to use "cmake-gui" or "ccmake" (shell). This document assumes you are using cmake-gui.
  1. Start "cmake-gui" and enter your source (e.g. "D:\AwesomeProject") and binary directory (e.g. "D:\AwesomeProject-superbuild").
  2. Upon first pressing "Configure" you will be prompted to select your generator. This determines what project files will be generated by %CMake. Set this to the development tool you are intending to use (e.g. "Visual Studio 2010 64Bit" or "linux makefiles".
  3. Press "Configure" until no new variables appear and then "Generate". Now all project files have been generated into your binary directory.
  4. Double-check that the right Qt version is used.
Now you are ready to compile your code. Depending on your choice of tool this will be done differently, we cover two possibilities here. \subsection HowToNewProjectCompilingLinuxMakefiles Compiling using linux makefiles
  1. In the shell, switch to your binary directory.
  2. type "make" and hit enter
\subsection HowToNewProjectCompilingVisualStudio Compiling using visual studio We assume your application is called "AwesomeApp" and your project "AwesomeProject" and your binary directory is "D:\AwesomeProject-superbuild\". Replace names and paths accordingly.
  1. Close %CMake and open "D:\AwesomeProject-superbuild\AwesomeProject-superbuild.sln" . Your Visual Studio should appear and by pressing F7 you start the compilation. This will clone the MITK source code, build it, and then start building your own project.
  2. After the superbuild compilation has finished, close the solution file and start the batch file "D:\AwesomeProject-superbuild\AwesomeProject-build\StartVS_debug.bat" (or _release.bat if you built in Release mode) which opens the "D:\AwesomeProject-superbuild\AweseomeProject-build\AwesomeProject.sln" solution.
  3. Set the "AwesomeApp" project as start-up project (right click > "Set as StartUp Project") and press "F5" to start your MITK AwesomeApp.
\note Just opening AwesomeProject.sln from your explorer by double-cliking won`t allow you to start or debug your application because the required environment variables would be missing. Use the supplied batch files or set your PATH variable accordingly. \section HowToNewProjectAddingMITKFunctionality I want to use some MITK plugin but it is not available Due to the sheer number of MITK plugins not every plugin is activated by default. To activate a specific plugin (again replace paths as needed):
  1. Start "cmake-gui" and set the binary directory to "D:\AwesomeProject-superbuild\MITK-superbuild\MITK-build\", the source will adjust automatically and you will see new settings appear.
  2. Navigate to the plugin you want to use (e.g. "MITK_BUILD_org.mitk.gui.qt.segmentation") and tick the checkbox behind it
  3. Press "Configure" until no new variables appear and then "Generate".
  4. Build MITK using your development tool (as in \ref HowToNewProjectCompilingLinuxMakefiles or \ref HowToNewProjectCompilingVisualStudio only in the "D:\AwesomeProject-superbuild\MITK-superbuild\MITK-build\" directory )
  5. Start "cmake-gui" and set the binary directory to "D:\AwesomeProject-superbuild\AwesomeProject-build\", the source will adjust automatically and you will see new settings appear.
  6. Press "Configure" until no new variables appear and then "Generate".
  7. Build your project
  8. Start your application
\note If you want to use an application provided by MITK (e.g. MITK Workbench) you have to tick the appropriate checkbox as well (in this case MITK_BUILD_APP_mitkWorkbench ) and build MITK. Do note, that this application will be located in the bin directory of the "D:\AwesomeProject-superbuild\MITK-superbuild\MITK-build\" folder. -\section HowToNewProjectAdvancedInformation Information for avanced users +\section HowToNewProjectAdvancedInformation Information for advanced users \subsection HowToNewProjectCustomizingMITK Customizing MITK The %CMake scripts from the Plugin Generator of the project template provide some handy options which allow you to customize the MITK build used in your project. You can either inject an already build MITK to be used by your project or configure some MITK options directly in your project's superbuild configuration if MITK is going to be build inside your project. \subsubsection HowToNewProjectCustomizingMITKInjectMITK Inject a MITK build By setting the \b EXTERNAL_MITK_DIR \b variable in your project's superbuild %CMake configuration to a MITK build directory (containing the MITKConfig.cmake) you can skip the MITK build process. If MITK is the only external project in your project, you might want to disable the superbuild of your project completely (set _USE_SUPERBUILD to OFF or edit your CMakeLists.txt file to set it to OFF by default) and set the \b MITK_DIR \b %CMake variable to your MITK build directory. \subsubsection HowToNewProjectCustomizingMITKConfigure Configure the MITK superbuild If MITK is being build inside your project's superbuild process, you can enable the use of certain third-party libraries inside of MITK. The following variables control the MITK configuration:
  • \b MITK_USE_BLUEBERRY Enable the use of the BlueBerry application framework
  • \b MITK_USE_Boost Download and use Boost in MITK
  • \b MITK_USE_CTK Download, compile, and use CTK in MITK
  • \b MITK_USE_DCMTK Download, compile, and use DCMTK in MITK
  • \b MITK_USE_OpenCV Download, compile, and use OpenCV in MITK
  • \b MITK_USE_Python Download and compile 1CableSwig and enable Python wrapping in ITK, VTK, OpenCV, and MITK
  • \b MITK_USE_QT Use the Qt framework in MITK
You can also inject already build third-party libraries from inside your project's superbuild in the MITK superbuild by using any of the following %CMake variables:
  • \b MITK_CTK_DIR Reuse a CTK build directory in MITK.
  • \b MITK_CableSwig_DIR Reuse a 1CableSwig build directory in MITK.
  • \b MITK_DCMTK_DIR Reuse a DCMKT build directory in MITK.
  • \b MITK_GDCM_DIR Reuse a GDCM build directory in MITK.
  • \b MITK_ITK_DIR Reuse a ITK build directory in MITK.
  • \b MITK_OpenCV_DIR Reuse a OpenCV build directory in MITK.
  • \b MITK_VTK_DIR Reuse a VTK build directory in MITK.
If the corresponding \b MITK_USE_ \b option is set to on, the MITK superbuild will use the provided build directory instead of building the project itself. You can also control the source code location for MITK in your project's superbuild configuration by using the following %CMake variables:
  • \b MITK_SOURCE_DIR The path to the MITK source directory. If the value for this variable is non-empty, the variables below are ignored.
  • \b MITK_GIT_REPOSITORY The Git repository containing the MITK source code.
  • \b MITK_GIT_TAG The hash id, tag or branch name used for a checkout from MITK_GIT_REPOSITORY.
\subsubsection HowToNewProjectProjectStructure Project Structure If you are using the superbuild feature of the generated project (the default), you might want to familiarise yourself with the layout of your build tree. The top-level build directory which you specified in %CMake when configuring your project will contain all the required dependencies. Suppose we call our project MyProject and the build directory is "C:\MyProject-superbuild". Then the layout looks something like this: MyProjectLayout.png The top-level directory contains the source code and the build directories from the dependencies of your project. In the current case, the only dependency of MyProject is MITK, which in turn has downloaded and built its own dependencies (CTK, DCMTK, ITK, etc.). The "real" build tree for your project is located in MyProject-superbuild/MyProject-build, so point the %CMake-GUI to this build directory if you want to change the set of enabled plug-ins for example. Further, you should open the MyProject.sln solution file (for Visual Studio) or execute "make" in the MyProject-superbuild/MyProject-build/ directory. Only for the very first time or if you want to update and newly build the project's dependencies should you use the project files in the MyProject-superbuild directory directly. The same applies for the MyProject-superbuild/MITK-superbuild directory. This directory contains the MITK superbuild, nested inside your project's superbuild. If you want to change %CMake options for MITK, use the MyProject-superbuild/MITK-superbuild/MITK-build build directory. \image html HowToNewProject-MyProjectLayout.png "Layout of MyProject" \subsubsection HowToNewProjectPackaging Packaging The project template and the generated projects by the Plugin Generator come with full packaging support. You can create deployable packages of your project for all supported operating systems my building the PACKAGE target. On Linux, this will create a tarball, on MacOS a .dmg file, and on Windows a zipball and an NSIS installer (if NSIS is installed and found). You can read more about deployment \ref DeploymentPage "here". */ \ No newline at end of file diff --git a/Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/SettingUpMITK.dox b/Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/SettingUpMITK.dox new file mode 100644 index 0000000000..5b67763c66 --- /dev/null +++ b/Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/SettingUpMITK.dox @@ -0,0 +1,14 @@ +/** +\page SettingUpMITK Setting Up Mitk + +TODO + +
    +
  • \subpage SupportedPlatformsPage
  • +
  • \subpage BuildInstructionsPage
  • +
  • \subpage thirdpartylibs
  • +
  • \subpage HowToNewProject
  • +
  • \subpage Testing
  • +
+ +*/ diff --git a/Documentation/Doxygen/DeveloperManual/SupportedPlatforms.md b/Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/SupportedPlatforms.md similarity index 100% rename from Documentation/Doxygen/DeveloperManual/SupportedPlatforms.md rename to Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/SupportedPlatforms.md diff --git a/Documentation/Doxygen/DeveloperManual/ThirdPartyLibs.dox b/Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox similarity index 100% rename from Documentation/Doxygen/DeveloperManual/ThirdPartyLibs.dox rename to Documentation/Doxygen/DeveloperManual/Starting/SettingUpMITK/ThirdPartyLibs.dox diff --git a/Documentation/Doxygen/DeveloperManual/Starting/Starting.dox b/Documentation/Doxygen/DeveloperManual/Starting/Starting.dox new file mode 100644 index 0000000000..fa78a1bb8d --- /dev/null +++ b/Documentation/Doxygen/DeveloperManual/Starting/Starting.dox @@ -0,0 +1,37 @@ +/** + +\page StartingDevelopment Starting your MITK Development + +This Introduction will acquaint you with the most important workflows to get you started with your MITK Development. + +
    +
  • \subpage Architecture
  • +
  • \subpage SettingUpMITK
  • +
      +
    • \ref SupportedPlatformsPage
    • +
    • \ref BuildInstructionsPage
    • +
    • \ref thirdpartylibs
    • +
    • \ref HowToNewProject
    • +
    +
  • \subpage GettingToKnowMITK
  • +
      +
    • \ref DirectoryStructurePage
    • +
    • \ref TutorialPage
    • +
    • \ref CMAKE_FAQ
    • +
    • \ref StyleGuideAndNotesPage
    • +
    • \ref DocumentationGuide
    • +
    • \ref CodingPage
    • +
    • \ref KnownProblemsPage
    • +
    +
  • \subpage FirstSteps
  • +
      +
    • \ref NewPluginPage
    • +
    • \ref NewModulePage
    • +
    • \ref StatemachineEditor
    • +
    +
  • \subpage AboutTestingPage
  • +
+ + + +*/ diff --git a/Documentation/Doxygen/DeveloperManual/Toolkit/DevelopmentToolkit.dox b/Documentation/Doxygen/DeveloperManual/Toolkit/DevelopmentToolkit.dox new file mode 100644 index 0000000000..ae77b729ea --- /dev/null +++ b/Documentation/Doxygen/DeveloperManual/Toolkit/DevelopmentToolkit.dox @@ -0,0 +1,13 @@ +/** + +\page DevelopmentToolkit Developing with the MITK Toolkit + +Todo + +
    +
  • \subpage Concepts
  • +
  • \subpage MITKModuleManualsListPage
  • +
+ + +*/ diff --git a/Documentation/Doxygen/UserManual/MITKModuleManualsList.dox b/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/MITKModuleManualsList.dox similarity index 93% rename from Documentation/Doxygen/UserManual/MITKModuleManualsList.dox rename to Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/MITKModuleManualsList.dox index 1cd4e1e54e..6dfede77e3 100644 --- a/Documentation/Doxygen/UserManual/MITKModuleManualsList.dox +++ b/Documentation/Doxygen/DeveloperManual/Toolkit/ModuleManuals/MITKModuleManualsList.dox @@ -1,20 +1,21 @@ /** \page MITKModuleManualsListPage MITK Module Manuals \section MITKModuleManualsListPageOverview Overview The modules are shared libraries that provide functionality that can be used by developers. \section MITKModuleManualsListPageModuleManualList List of Module Manuals \li \subpage IGTGeneralModulePage \li \subpage MitkOpenCL_Overview \li \subpage SimulationManualPage + \li \subpage GeneratingDeviceModulesPage \section MITKModuleManualsListPageAdditionalInformation Additional Information on Certain Modules \li \ref PlanarPropertiesPage \li \subpage DiffusionImagingPropertiesPage \li \subpage ConnectomicsRenderingPropertiesPage */ diff --git a/Core/Documentation/Doxygen/Concepts/images/introduction/MitkOverview.png b/Documentation/Doxygen/DeveloperManual/images/MitkOverview.png similarity index 100% rename from Core/Documentation/Doxygen/Concepts/images/introduction/MitkOverview.png rename to Documentation/Doxygen/DeveloperManual/images/MitkOverview.png diff --git a/Documentation/Doxygen/MainPage.dox.in b/Documentation/Doxygen/MainPage.dox.in index 05d7565451..ed93fcfd62 100644 --- a/Documentation/Doxygen/MainPage.dox.in +++ b/Documentation/Doxygen/MainPage.dox.in @@ -1,57 +1,17 @@ /** -\mainpage Medical Imaging Interaction Toolkit +\mainpage Medical Imaging Interaction Toolkit - Documentation Portal \image html mitkLogo.jpg -\section intro Introduction +This page acts as a portal to the three different parts of the MITK-Documentation. -Welcome to the Medical Imaging Interaction Toolkit (MITK). -Currently under active development, MITK aims at supporting the -development of leading-edge medical imaging software -with a high degree of interaction. It combines VTK, -ITK and the pic-based-libraries of the -Div. Medical and Biological Informatics -of the DKFZ and adds those features that are most important -for developing interactive medical imaging software covered neither by VTK nor ITK, i.e: -\li multiple, consistent views on the same data. For example, when you have three orthogonal -2D-views and a 3D view and data consisting of a green surface, the surface will be visible and green -in all views (as contour lines in 2D, as a surface in 3D), and when you move the surface, it will -move in all views. When you try to implement this with basic VTK, you will need to coordinate the -position/orientation/color/... of all the views somewhere in your program - exactly this can MITK -do for you. -\li interactions that create and/or modify data (not only actors as in basic VTK) -\li complex interactions with multiple states, e.g., for interaction with active contours -\li undo/redo of interactions -\li organization of data objects in a tree at run-time, e.g., to represent logical dependencies (e.g., -a heart cavity is a part of the heart) or to control the rendering process -\li additional properties of arbitrary type can be assigned to data objects contained in the data tree -\li visualization and interaction with 3D+t data (basic VTK can handle only 3D data and ITK is not -for visualization and interaction) -\li although MITK is mainly a toolkit and not an application, it offers some support on the -application-level, e.g, for structured combination of modules (so-called functionalities), e.g., for -combining and switching between one functionality for segmentation and another for registration. +If this is your first time around here and you are interested in learning more about MITK, please read \subpage Overview -MITK re-uses virtually anything from VTK and ITK. Thus, it is not at all a competitor to VTK or ITK, but -an extension, which tries to ease the combination of both and to add the features outlined above. +If you are a MITK end-user, please refer to the \subpage UserManualPortal -\section FurtherReading Further Reading +If you are a developer looking for a developer's guide, please see \subpage DeveloperManualPortal -\subpage ShortIntroductionToMITK - -\ref Concepts - -\ref Development - -\ref HowToNewProject "A comprehensive newcomers guide to setting up your own MITK project" - -@MITK_XP_LINK@ - -@BLUEBERRY_DOXYGEN_LINK@ - -\ref thirdpartylibs - - */ diff --git a/Documentation/Doxygen/ModuleDataManagementClasses.dox.template b/Documentation/Doxygen/ModuleDataManagementClasses.dox.template deleted file mode 100644 index e3a706d3fc..0000000000 --- a/Documentation/Doxygen/ModuleDataManagementClasses.dox.template +++ /dev/null @@ -1,93 +0,0 @@ -/** - \defgroup DataManagement Data Management Classes - - \brief This category includes the data classes themselves as well as management classes to organize the - data during run-time in a tree structure. - - Available sections: - - \ref overview - - \ref inthisgroup - - \ref notinthisgroup - - \ref seealso - - \ref future - - \ref changes - - \section overview Rationale and overview - - kurze Zusammenfassung - -Ich bin Blindtext. Von Geburt an. Es hat lange gedauert, bis ich begriffen habe, -was es bedeutet, ein blinder Text zu sein: Man macht keinen Sinn. Man wirkt hier -und da aus dem Zusammenhang gerissen. Oft wird man gar nicht erst gelesen. - -Aber bin ich deshalb ein schlechter Text? Ich weiss, dass ich nie die Chance -haben werde, im Stern zu erscheinen. Aber bin ich darum weniger wichtig? -Ich bin blind! Aber ich bin gerne Text. Und sollten Sie mich jetzt tatsaechlich zu -Ende lesen, dann habe ich etwas geschafft, was den meisten "normalen" Texten nicht -gelingt. - -Übrigens: lieber &uuml; statt ü schreiben. und &amp; und &szlig; Und noch besser einfach englisch ohne Umlaute. - -\em Ein \e Code-Block -\code -#include - -class QUndoRedoButtonPlugin : public QWidgetPlugin -{ -public: - QUndoRedoButtonPlugin(); - - QStringList keys() const; - QWidget* create( const QString &classname, QWidget* parent = 0, const char* name = 0 ); - QString group( const QString& ) const; - QIconSet iconSet( const QString& ) const; - QString includeFile( const QString& ) const; - QString toolTip( const QString& ) const; - QString whatsThis( const QString& ) const; - bool isContainer( const QString& ) const; -}; -\endcode - -Ein \c Verbatim-Absatz: - - -cd /src - cvs -d :pserver:anonymous@mbi.dkfz-heidelberg.de:/usr/local/cvsroot login
-cvs -d :pserver:anonymous@mbi.dkfz-heidelberg.de:/usr/local/cvsroot co mitk -
- -Und noch ein Bild: - -\image html step4a_result.png "Bildunterschrift" -\image latex step4a_result.png "Bildunterschrift" - -Eine kleine Aufzählung: - -\li \ref Step4.cpp "Step4.cpp"\n -Contains the code of step 4a + b. -\li \ref Step4.cpp "Step4.cpp"\n -Contains the code of step 4a + b. -\li \ref Step4.cpp "Step4.cpp"\n -Contains the code of step 4a + b. - - - \subsection inthisgroup What belongs into this group - Beispiel - \subsection notinthisgroup What belongs not into this group - evtl. Gegenbeispiel - - - \section seealso See also - - \ref DataManagement, - \ref Geometry - - \section future Plans for the future - - \section changes Major changes since version x - - wenns denn mal zutrifft - -*/ - - diff --git a/Documentation/Doxygen/Modules/ModuleGeometryFigures.zip b/Documentation/Doxygen/Modules/ModuleGeometryFigures.zip deleted file mode 100644 index 434c701fb9..0000000000 Binary files a/Documentation/Doxygen/Modules/ModuleGeometryFigures.zip and /dev/null differ diff --git a/Documentation/Doxygen/Modules/RenderingSequence.png b/Documentation/Doxygen/Modules/RenderingSequence.png deleted file mode 100644 index 5e5a64bb21..0000000000 Binary files a/Documentation/Doxygen/Modules/RenderingSequence.png and /dev/null differ diff --git a/Documentation/Doxygen/Modules/RenderingSequence.vsd b/Documentation/Doxygen/Modules/RenderingSequence.vsd deleted file mode 100644 index 6a6e7ab060..0000000000 Binary files a/Documentation/Doxygen/Modules/RenderingSequence.vsd and /dev/null differ diff --git a/Documentation/Doxygen/Modules/dialogbarSlicer.png b/Documentation/Doxygen/Modules/dialogbarSlicer.png deleted file mode 100644 index 839a4d94be..0000000000 Binary files a/Documentation/Doxygen/Modules/dialogbarSlicer.png and /dev/null differ diff --git a/Documentation/Doxygen/Modules/dialogbarStandardViews.png b/Documentation/Doxygen/Modules/dialogbarStandardViews.png deleted file mode 100644 index 570003ecfc..0000000000 Binary files a/Documentation/Doxygen/Modules/dialogbarStandardViews.png and /dev/null differ diff --git a/Documentation/Doxygen/Modules/dialogbarStereoOptions.png b/Documentation/Doxygen/Modules/dialogbarStereoOptions.png deleted file mode 100644 index 0440c2a04d..0000000000 Binary files a/Documentation/Doxygen/Modules/dialogbarStereoOptions.png and /dev/null differ diff --git a/Documentation/Doxygen/Modules/dialogbarbuttons.png b/Documentation/Doxygen/Modules/dialogbarbuttons.png deleted file mode 100644 index 5626290498..0000000000 Binary files a/Documentation/Doxygen/Modules/dialogbarbuttons.png and /dev/null differ diff --git a/Documentation/Doxygen/Modules/functionalityButtons.png b/Documentation/Doxygen/Modules/functionalityButtons.png deleted file mode 100644 index dfb7b1bf83..0000000000 Binary files a/Documentation/Doxygen/Modules/functionalityButtons.png and /dev/null differ diff --git a/Documentation/Doxygen/Modules/renderwindowOptions.png b/Documentation/Doxygen/Modules/renderwindowOptions.png deleted file mode 100644 index 08c1eda9b5..0000000000 Binary files a/Documentation/Doxygen/Modules/renderwindowOptions.png and /dev/null differ diff --git a/Documentation/Doxygen/Modules/renderwindows.png b/Documentation/Doxygen/Modules/renderwindows.png deleted file mode 100644 index 6d781311c8..0000000000 Binary files a/Documentation/Doxygen/Modules/renderwindows.png and /dev/null differ diff --git a/Documentation/Doxygen/Modules/undoredobutton.png b/Documentation/Doxygen/Modules/undoredobutton.png deleted file mode 100644 index 16cc086f8b..0000000000 Binary files a/Documentation/Doxygen/Modules/undoredobutton.png and /dev/null differ diff --git a/Documentation/Doxygen/DeveloperManual/ShortIntroductionToMITK.dox b/Documentation/Doxygen/Overview/Overview.dox similarity index 96% rename from Documentation/Doxygen/DeveloperManual/ShortIntroductionToMITK.dox rename to Documentation/Doxygen/Overview/Overview.dox index 9b03af2ba5..565f32e6f2 100644 --- a/Documentation/Doxygen/DeveloperManual/ShortIntroductionToMITK.dox +++ b/Documentation/Doxygen/Overview/Overview.dox @@ -1,29 +1,29 @@ /** -\page ShortIntroductionToMITK A short introduction to MITK +\page Overview MITK: An Overview The Medical Imaging Interaction Toolkit (MITK) can be used in several different ways. If you are a new user to MITK the first question is in what manner you intend to use it. The following options are simplified and condensed versions of the most common usage scenarios. \tableofcontents \section ShortIntroductionToMITKAsToolkit I want to develop my own software framework, but use some of MITK's data structures and algorithms You will use MITK as a toolkit and probably benefit most from the \ref BuildInstructionsPage and MITK API Documentation. \section ShortIntroductionToMITKAsFramework I want to use the MITK and BlueBerry software framework to develop my own software Here you have again two options. \subsection ShortIntroductionToMITKAsFrameworkExtendingWorkbench I want use the MITK Workbench and extend its capabilities You are using MITK as software framework and writing your own modules and plugins for MITK. You want to read the \ref BuildInstructionsPage and further on \ref Development. Also you might want to take a look at our \ref CMAKE_FAQ. \subsection ShortIntroductionToMITKAsFrameworkExternalProject I want to create my own application based on MITK but with major customizations and changes This is probably the most common way to use MITK. You are using MITK as software framework and building your own project and application using MITK. You want to read \ref HowToNewProject and the general information in \ref Development. Also you might want to take a look at our \ref CMAKE_FAQ. \section ShortIntroductionToMITKAsFrameworkEndUser I want to use the MITK Workbench to do image processing You are using MITK and the MITK Workbench as an end user and will find user manuals in \ref MITKUserManualPage and \ref PluginListPage. */ \ No newline at end of file diff --git a/Documentation/Doxygen/Tutorial/CMakeLists.txt b/Documentation/Doxygen/Tutorial/CMakeLists.txt deleted file mode 100644 index 8b13789179..0000000000 --- a/Documentation/Doxygen/Tutorial/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/Documentation/Doxygen/Tutorial/Step09.dox b/Documentation/Doxygen/Tutorial/Step09.dox deleted file mode 100644 index f804f36bba..0000000000 --- a/Documentation/Doxygen/Tutorial/Step09.dox +++ /dev/null @@ -1,219 +0,0 @@ -/** - -\page Step09Page MITK Tutorial - Step 9: A plug-in - -MITK uses a very modular concept to maximize reusability and portability. You start an application (for example mitkWorkbench, the sample application provided by MITK). An application has several bundles (or plug-ins). A bundle can be a functionality, which in turn can be a view, each of these terms specifying certain behaviour and attributes. - -The creation of a MITK plug-in is considerably facilitated by using the MITK BundleGenerator as described in \ref NewPluginPage . - -The mentioned tool was used to create a plug-in QmitkRegionGrowing. -Let's first look at what files the BundleGenerator created: - -\verbatim -documentation\doxygen\ - modules.dox............................. Doxygen file for documenting your plug-in - -resources\ - icon.xpm................................ The icon of your plug-in. GIMP or other programs (including your text editor) - can be used to change this - -src\internal\ - QmitkMITKRegionGrowingView.cpp.......... The most important file, implementing behaviour - QmitkMITKRegionGrowingView.h............ Header file of the functionality - QmitkMITKRegionGrowingViewControls.ui... XML file of the Qt Designer, describes buttons, combo boxes, etc. of your controls - -CMakeLists.txt \.......................... Build system related files for CMake -files.cmake / -manifest_headers.cmake.................... Information about your plug-in -plugin.xml ............................... BlueBerry integration -\endverbatim - -If you are not familiar with Qt development, please look into -this Trolltech page describing .ui files (no, forget about the please, DO it!) - -The C++ files implement a subclass of QmitkAbstractView. In this special case of QmitkRegionGrowing, we added the ability to set some seed points and run a region grower. If you are interested in the concrete changes necessary to turn a freshly generated QmitkRegionGrowing into an integrated one: - -Since an access to the StdMultiWidget is needed, manifest_headers.cmake has to be edited: -\verbatim -set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.stdmultiwidgeteditor) -\endverbatim - -To add a PointSet for the seed points: -QmitkRegionGrowingView.h - -Add includes: -\verbatim -#include "QmitkPointListWidget.h" -#include "QmitkStdMultiWidget.h" -#include "QmitkStdMultiWidgetEditor.h" -\endverbatim - -Add the point set as protected object and add Pointers for a QmitkPointListWidget and a QmitkStdMultiWidget: -\verbatim -/// \brief This is the actual seed point data object -mitk::PointSet::Pointer m_PointSet; - -QmitkPointListWidget* lstPoints; -QmitkStdMultiWidget* m_MultiWidget; -\endverbatim - -QmitkRegionGrowingView.cpp - -CreateQtPartControl(): -\verbatim -// create a QmitkPointListWidget and add it to the widget created from .ui file -lstPoints = new QmitkPointListWidget(); -m_Controls.verticalLayout->addWidget(lstPoints); - -// get access to StdMultiWidget by using RenderWindowPart -QmitkStdMultiWidgetEditor* qSMWE = dynamic_cast(GetRenderWindowPart()); -m_MultiWidget = qSMWE->GetStdMultiWidget(); - -// let the point set widget know about the multi widget (crosshair updates) -lstPoints->SetMultiWidget( m_MultiWidget ); - -// create a new DataTreeNode containing a PointSet with some interaction -m_PointSet = mitk::PointSet::New(); - -mitk::DataNode::Pointer pointSetNode = mitk::DataNode::New(); -pointSetNode->SetData( m_PointSet ); -pointSetNode->SetName("seed points for region growing"); -pointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true) ); -pointSetNode->SetProperty("layer", mitk::IntProperty::New(1024) ); - -// add the pointset to the data tree (for rendering and access by other modules) -GetDataStorage()->Add( pointSetNode ); - -// tell the GUI widget about out point set -lstPoints->SetPointSetNode( pointSetNode ); -\endverbatim - -To use the ITK region grower: - -QmitkRegionGrowingView.h - -Add protected method: -\verbatim -/*! -\brief ITK image processing function - This function is templated like an ITK image. The MITK-Macro AccessByItk determines the actual pixel type and dimensionality of - a given MITK image and calls this function for further processing (in our case region growing) -*/ -template < typename TPixel, unsigned int VImageDimension > - void ItkImageProcessing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry ); -\endverbatim - -QmitkRegionGrowingView.cpp - -Add includes: -\verbatim -// MITK -#include "mitkImageAccessByItk.h" -#include "mitkITKImageImport.h" -#include "mitkProperties.h" -#include "mitkColorProperty.h" - -// ITK -#include - -\endverbatim - -DoImageProcessing(); -\verbatim -// So we have an image. Let's see if the user has set some seed points already -if ( m_PointSet->GetSize() == 0 ) -{ - // no points there. Not good for region growing - QMessageBox::information( NULL, "Region growing functionality", - "Please set some seed points inside the image first.\n" - "(hold Shift key and click left mouse button inside the image.)" - ); - return; -} - -// actually perform region growing. Here we have both an image and some seed points -AccessByItk_1( image, ItkImageProcessing, image->GetGeometry() ); // some magic to call the correctly templated function -\endverbatim - -And add the new method: -\verbatim -template < typename TPixel, unsigned int VImageDimension > -void QmitkRegionGrowingView::ItkImageProcessing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry ) -{ - typedef itk::Image< TPixel, VImageDimension > InputImageType; - typedef typename InputImageType::IndexType IndexType; - - // instantiate an ITK region growing filter, set its parameters - typedef itk::ConnectedThresholdImageFilter RegionGrowingFilterType; - typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New(); - regionGrower->SetInput( itkImage ); // don't forget this - - // determine a thresholding interval - IndexType seedIndex; - TPixel min( std::numeric_limits::max() ); - TPixel max( std::numeric_limits::min() ); - mitk::PointSet::PointsContainer* points = m_PointSet->GetPointSet()->GetPoints(); - for ( mitk::PointSet::PointsConstIterator pointsIterator = points->Begin(); - pointsIterator != points->End(); - ++pointsIterator ) - { - // first test if this point is inside the image at all - if ( !imageGeometry->IsInside( pointsIterator.Value()) ) - { - continue; - } - - // convert world coordinates to image indices - imageGeometry->WorldToIndex( pointsIterator.Value(), seedIndex); - - // get the pixel value at this point - TPixel currentPixelValue = itkImage->GetPixel( seedIndex ); - - // adjust minimum and maximum values - if (currentPixelValue > max) - max = currentPixelValue; - - if (currentPixelValue < min) - min = currentPixelValue; - - regionGrower->AddSeed( seedIndex ); - } - - MITK_INFO << "Values between " << min << " and " << max; - - min -= 30; - max += 30; - - // set thresholds and execute filter - regionGrower->SetLower( min ); - regionGrower->SetUpper( max ); - - regionGrower->Update(); - - mitk::Image::Pointer resultImage = mitk::ImportItkImage( regionGrower->GetOutput() ); - mitk::DataNode::Pointer newNode = mitk::DataNode::New(); - newNode->SetData( resultImage ); - - // set some properties - newNode->SetProperty("binary", mitk::BoolProperty::New(true)); - newNode->SetProperty("name", mitk::StringProperty::New("dumb segmentation")); - newNode->SetProperty("color", mitk::ColorProperty::New(1.0,0.0,0.0)); - newNode->SetProperty("volumerendering", mitk::BoolProperty::New(true)); - newNode->SetProperty("layer", mitk::IntProperty::New(1)); - newNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); - - // add result to data tree - this->GetDataStorage()->Add( newNode ); - mitk::RenderingManager::GetInstance()->RequestUpdateAll(); -} - -\endverbatim - -Have fun using MITK! - -If you meet any difficulties during your first steps, don't hesitate to ask on the MITK mailing list mitk-users@lists.sourceforge.net! -People there are kind and will try to help you. - - \ref Step08Page "[Previous step]" \ref Step10Page "[Next Step]" \ref TutorialPage "[Main tutorial page]" - -*/ diff --git a/Documentation/Doxygen/UserManual/Applications.dox b/Documentation/Doxygen/UserManual/Applications.dox index 2a6b7db404..7620fc8046 100644 --- a/Documentation/Doxygen/UserManual/Applications.dox +++ b/Documentation/Doxygen/UserManual/Applications.dox @@ -1,30 +1,30 @@ /** \page ApplicationsPage Using MITK and Applications Available sections: - \ref ApplicationsPageUsingMITK - \ref ApplicationsPageApplications - \ref ApplicationsPageApplicationsList \section ApplicationsPageUsingMITK Using MITK Many of the applications created with the use of MITK share common basic functionalities. Due to this, there is one manual which explains the basic usage of MITK. For more information on the use of the advanced features of an application please take a look the \ref ApplicationsPageApplicationsList , whereas if you are interested in a certain view further information can be found in \ref PluginListPage . -The basic usage information on MITK can be found in \subpage MITKUserManualPage . +The basic usage information on MITK can be found in \ref MITKUserManualPage . \section ApplicationsPageApplications What are Applications? Applications are executables, which contain a certain configuration of views and perspectives. Usually they are aimed at a selective audience or solving a particular problem. As such they focus on certain capabilities of MITK, while ignoring others. The main reason for this is to supply the users of the application with the power of MITK for solving their tasks, without daunting them with an overwhelming number of menus and options. At the same time, this allows, together with the use of perspectives, the creation of sleek and elegant workflows, which are easily comprehensible. A typical example of this would be an application which contains only views related to the analysis of the human brain (particular question) or one which contains only what is necessary for displaying medical data in the classroom (specific audience). \section ApplicationsPageApplicationsList List of Applications If you are interested in using a specific application, currently developed by the MITK team you might want to take a look first at the \ref MITKUserManualPage . Further information on any application can be found here:
  • \subpage org_mitkworkbench
  • \subpage org_dti_atlas_application
  • \subpage org_mitk_gui_qt_diffusionimagingapp
*/ \ No newline at end of file diff --git a/Documentation/Doxygen/UserManual/MITKPluginManualsList.dox b/Documentation/Doxygen/UserManual/MITKPluginManualsList.dox index 26c53b8a28..a80b2c16f6 100644 --- a/Documentation/Doxygen/UserManual/MITKPluginManualsList.dox +++ b/Documentation/Doxygen/UserManual/MITKPluginManualsList.dox @@ -1,37 +1,41 @@ /** \page PluginListPage MITK Plugin Manuals \section PluginListPageOverview Overview The plugins and bundles provide much of the extended functionality of MITK. Each encapsulates a solution to a problem and associated features. This way one can easily assemble the necessary capabilites for a workflow without adding a lot of bloat, by combining plugins as needed. The distinction between developer and end user use is for convenience only and mainly distinguishes which group a plugin is primarily aimed at. \section PluginListPageEndUserPluginList List of Plugins for End User Use + \li \subpage org_blueberry_ui_qt_log \li \subpage org_mitk_views_basicimageprocessing \li \subpage org_mitk_views_datamanager \li \subpage org_mitk_gui_qt_diffusionimaging \li \subpage org_mitk_views_imagecropper \li \subpage org_mitk_views_imagenavigator \li \subpage org_mitk_gui_qt_measurementtoolbox \li \subpage org_mitk_views_moviemaker \li \subpage org_mitk_views_meshdecimation \li \subpage org_mitk_views_pointsetinteraction \li \subpage org_mitk_gui_qt_registration \li \subpage org_mitk_views_segmentation \li \subpage org_mitk_views_volumevisualization \li \subpage org_mitk_gui_qt_dicom \li \subpage org_mitk_gui_qt_ultrasound + \li \subpage org_mitk_views_fiberfoxview \section PluginListPageDevPluginList List of Plugins for Developer Use and Examples \li \subpage org_surfacematerialeditor \li \subpage org_toftutorial \li \subpage org_mitk_gui_qt_examples \li \subpage org_mitkexamplesopencv \li \ref org_mitk_gui_qt_igtexample \li \ref org_mitk_gui_qt_igttracking + \li \subpage org_blueberry_ui_qt_objectinspector + \li \subpage org_mitk_gui_InteractionTests */ diff --git a/Documentation/Doxygen/UserManual/UserManualPortal.dox b/Documentation/Doxygen/UserManual/UserManualPortal.dox new file mode 100644 index 0000000000..83d3a73e5b --- /dev/null +++ b/Documentation/Doxygen/UserManual/UserManualPortal.dox @@ -0,0 +1,9 @@ +/** +\page UserManualPortal MITK: User Manual + +
    +
  • \subpage ApplicationsPage
  • +
  • \subpage MITKUserManualPage
  • +
  • \subpage PluginListPage
  • +
+*/ \ No newline at end of file diff --git a/Documentation/MITKDoxygenLayout.xml b/Documentation/MITKDoxygenLayout.xml index 19afb000f9..96f50c0087 100644 --- a/Documentation/MITKDoxygenLayout.xml +++ b/Documentation/MITKDoxygenLayout.xml @@ -1,188 +1,197 @@ - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + diff --git a/Documentation/doxygen.conf.in b/Documentation/doxygen.conf.in index cdc2768b89..7347fa1b56 100644 --- a/Documentation/doxygen.conf.in +++ b/Documentation/doxygen.conf.in @@ -1,1921 +1,1921 @@ # Doxyfile 1.8.0 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = MITK # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = @MITK_VERSION_STRING@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = "Medical Imaging Interaction Toolkit" # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = @MITK_DOXYGEN_OUTPUT_DIR@ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = "FIXME=\par Fix Me's:\n" \ "BlueBerry=\if BLUEBERRY" \ "endBlueBerry=\endif" \ "bundlemainpage{1}=\page \1" \ "embmainpage{1}=\page \1" \ "github{2}=\2" \ "deprecatedSince{1}=\xrefitem deprecatedSince\1 \" Deprecated as of \1\" \"Functions deprecated as of \1\" " # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding # "class=itcl::class" will allow you to use the command class in the # itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all # comments according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you # can mix doxygen, HTML, and XML commands with Markdown formatting. # Disable only in case of backward compatibilities issues. MARKDOWN_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = YES # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. SYMBOL_CACHE_SIZE = 0 # Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be # set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given # their name and scope. Since this can be an expensive process and often the # same symbol appear multiple times in the code, doxygen keeps a cache of # pre-resolved symbols. If the cache is too small doxygen will become slower. # If the cache is too large, memory is wasted. The cache size is given by this # formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = @MITK_DOXYGEN_INTERNAL_DOCS@ # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = @MITK_DOXYGEN_HIDE_FRIEND_COMPOUNDS@ # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = @MITK_DOXYGEN_INTERNAL_DOCS@ # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = YES # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = @MITK_DOXYGEN_GENERATE_TODOLIST@ # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = @MITK_DOXYGEN_GENERATE_BUGLIST@ # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= @MITK_DOXYGEN_GENERATE_DEPRECATEDLIST@ # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = @MITK_DOXYGEN_ENABLED_SECTIONS@ # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 0 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = @MITK_SOURCE_DIR@/Documentation/MITKDoxygenLayout.xml # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this # feature you need bibtex and perl available in the search path. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = @MITK_SOURCE_DIR@ \ @MITK_BINARY_DIR@ \ @MITK_DOXYGEN_ADDITIONAL_INPUT_DIRS@ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.h \ *.cpp \ *.dox \ *.md \ *.txx \ *.tpp \ *.cxx \ *.cmake # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = @MITK_SOURCE_DIR@/Utilities/ann/ \ +EXCLUDE = @MITK_SOURCE_DIR@/BlueBerry/Documentation/reference/api/MainPage.dox \ + @MITK_SOURCE_DIR@/Utilities/ann/ \ @MITK_SOURCE_DIR@/Utilities/glew/ \ @MITK_SOURCE_DIR@/Utilities/ipFunc/ \ @MITK_SOURCE_DIR@/Utilities/ipSegmentation/ \ @MITK_SOURCE_DIR@/Utilities/KWStyle/ \ @MITK_SOURCE_DIR@/Utilities/pic2vtk/ \ @MITK_SOURCE_DIR@/Utilities/Poco/ \ @MITK_SOURCE_DIR@/Utilities/qtsingleapplication/ \ @MITK_SOURCE_DIR@/Utilities/qwt/ \ @MITK_SOURCE_DIR@/Utilities/qxt/ \ @MITK_SOURCE_DIR@/Utilities/tinyxml/ \ @MITK_SOURCE_DIR@/Utilities/vecmath/ \ @MITK_SOURCE_DIR@/Applications/PluginGenerator/ \ - @MITK_SOURCE_DIR@/BlueBerry/ \ @MITK_SOURCE_DIR@/Core/Code/CppMicroServices/README.md \ @MITK_SOURCE_DIR@/Core/Code/CppMicroServices/documentation/snippets/ \ @MITK_SOURCE_DIR@/Core/Code/CppMicroServices/documentation/doxygen/standalone/ \ @MITK_SOURCE_DIR@/Core/Code/CppMicroServices/test/ \ @MITK_SOURCE_DIR@/Deprecated/ \ @MITK_SOURCE_DIR@/Build/ \ @MITK_SOURCE_DIR@/CMake/PackageDepends \ @MITK_SOURCE_DIR@/CMake/QBundleTemplate \ @MITK_SOURCE_DIR@/CMakeExternals \ @MITK_SOURCE_DIR@/Modules/QmitkExt/vtkQtChartHeaders/ \ @MITK_BINARY_DIR@/PT/ \ @MITK_BINARY_DIR@/GP/ \ @MITK_BINARY_DIR@/Core/Code/CppMicroServices/ \ - @MITK_BINARY_DIR@/BlueBerry/ \ @MITK_DOXYGEN_ADDITIONAL_EXCLUDE_DIRS@ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = moc_* \ ui_* \ qrc_* \ wrap_* \ Register* \ */files.cmake \ */.git/* \ *_p.h \ *Private.* \ */Snippets/* \ */snippets/* \ */testing/* \ */Testing/* \ @MITK_BINARY_DIR@/*.cmake \ @MITK_DOXYGEN_EXCLUDE_PATTERNS@ # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = @MITK_SOURCE_DIR@/Examples/ \ @MITK_SOURCE_DIR@/Examples/Tutorial/ \ - @MITK_SOURCE_DIR@/Examples/Plugins/ \ + @MITK_SOURCE_DIR@/Examples/Plugins/ \ @MITK_SOURCE_DIR@/Examples/QtFreeRender/ \ @MITK_SOURCE_DIR@/Core/Code/ \ @MITK_SOURCE_DIR@/Core/Code/CppMicroServices/Documentation/Snippets/ \ @MITK_DOXYGEN_OUTPUT_DIR@/html/extension-points/html/ \ @MITK_SOURCE_DIR@/Documentation/Snippets/ \ @MITK_SOURCE_DIR@/Documentation/Doxygen/ExampleCode/ \ - @MITK_SOURCE_DIR@/Modules/OpenCL/Documentation/doxygen/snippets/ + @MITK_SOURCE_DIR@/Modules/OpenCL/Documentation/doxygen/snippets/ \ + @MITK_SOURCE_DIR@/BlueBerry/Documentation/snippets/ # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = YES # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = @MITK_SOURCE_DIR@/Documentation/Doxygen/ \ @MITK_SOURCE_DIR@/Documentation/Doxygen/Modules/ \ @MITK_SOURCE_DIR@/Documentation/Doxygen/Tutorial/ \ @MITK_SOURCE_DIR@ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = *.cmake=@CMakeDoxygenFilter_EXECUTABLE@ # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 3 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is advised to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = @MITK_DOXYGEN_STYLESHEET@ # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the style sheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = @MITK_DOXYGEN_HTML_DYNAMIC_SECTIONS@ # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = @MITK_DOXYGEN_GENERATE_QHP@ # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = @MITK_DOXYGEN_QCH_FILE@ # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = "org.mitk" # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = MITK # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = @QT_HELPGENERATOR_EXECUTABLE@ # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) # at top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. Since the tabs have the same information as the # navigation tree you can set this option to NO if you already set # GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. # Since the tree basically has the same information as the tab index you # could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 300 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you may also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to # the MathJax Content Delivery Network so you can quickly see the result without # installing MathJax. # However, it is strongly recommended to install a local # copy of MathJax from http://www.mathjax.org before deployment. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = amssymb # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = itkNotUsed(x)= \ "itkSetMacro(name,type)= virtual void Set##name (type _arg);" \ "itkGetMacro(name,type)= virtual type Get##name ();" \ "itkGetConstMacro(name,type)= virtual type Get##name () const;" \ "itkSetStringMacro(name)= virtual void Set##name (const char* _arg);" \ "itkGetStringMacro(name)= virtual const char* Get##name () const;" \ "itkSetClampMacro(name,type,min,max)= virtual void Set##name (type _arg);" \ "itkSetObjectMacro(name,type)= virtual void Set##name (type* _arg);" \ "itkGetObjectMacro(name,type)= virtual type* Get##name ();" \ "itkSetConstObjectMacro(name,type)= virtual void Set##name ( const type* _arg);" \ "itkGetConstObjectMacro(name,type)= virtual const type* Get##name ();" \ "itkGetConstReferenceMacro(name,type)= virtual const type& Get##name ();" \ "itkGetConstReferenceObjectMacro(name,type)= virtual const type::Pointer& Get##name () const;" \ "itkBooleanMacro(name)= virtual void name##On (); virtual void name##Off ();" \ "itkSetVector2Macro(name,type)= virtual void Set##name (type _arg1, type _arg2) virtual void Set##name (type _arg[2]);" \ "itkGetVector2Macro(name,type)= virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2) const; virtual void Get##name (type _arg[2]) const;" \ "itkSetVector3Macro(name,type)= virtual void Set##name (type _arg1, type _arg2, type _arg3) virtual void Set##name (type _arg[3]);" \ "itkGetVector3Macro(name,type)= virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2, type& _arg3) const; virtual void Get##name (type _arg[3]) const;" \ "itkSetVector4Macro(name,type)= virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4) virtual void Set##name (type _arg[4]);" \ "itkGetVector4Macro(name,type)= virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2, type& _arg3, type& _arg4) const; virtual void Get##name (type _arg[4]) const;" \ "itkSetVector6Macro(name,type)= virtual void Set##name (type _arg1, type _arg2, type _arg3, type _arg4, type _arg5, type _arg6) virtual void Set##name (type _arg[6]);" \ "itkGetVector6Macro(name,type)= virtual type* Get##name () const; virtual void Get##name (type& _arg1, type& _arg2, type& _arg3, type& _arg4, type& _arg5, type& _arg6) const; virtual void Get##name (type _arg[6]) const;" \ "itkSetVectorMacro(name,type,count)= virtual void Set##name(type data[]);" \ "itkGetVectorMacro(name,type,count)= virtual type* Get##name () const;" \ "itkNewMacro(type)= static Pointer New();" \ "itkTypeMacro(thisClass,superclass)= virtual const char *GetClassName() const;" \ "itkConceptMacro(name,concept)= enum { name = 0 };" \ "ITK_NUMERIC_LIMITS= std::numeric_limits" \ "ITK_TYPENAME= typename" \ "FEM_ABSTRACT_CLASS(thisClass,parentClass)= public: /** Standard Self typedef.*/ typedef thisClass Self; /** Standard Superclass typedef. */ typedef parentClass Superclass; /** Pointer or SmartPointer to an object. */ typedef Self* Pointer; /** Const pointer or SmartPointer to an object. */ typedef const Self* ConstPointer; private:" \ "FEM_CLASS(thisClass,parentClass)= FEM_ABSTRACT_CLASS(thisClass,parentClass) public: /** Create a new object from the existing one */ virtual Baseclass::Pointer Clone() const; /** Class ID for FEM object factory */ static const int CLID; /** Virtual function to access the class ID */ virtual int ClassID() const { return CLID; } /** Object creation in an itk compatible way */ static Self::Pointer New() { return new Self(); } private:" \ FREEVERSION \ ERROR_CHECKING \ HAS_TIFF \ HAS_JPEG \ HAS_NETLIB \ HAS_PNG \ HAS_ZLIB \ HAS_GLUT \ HAS_QT \ VCL_USE_NATIVE_STL=1 \ VCL_USE_NATIVE_COMPLEX=1 \ VCL_HAS_BOOL=1 \ VXL_BIG_ENDIAN=1 \ VXL_LITTLE_ENDIAN=0 \ VNL_DLL_DATA= \ size_t=vcl_size_t \ "US_PREPEND_NAMESPACE(x)=mitk::x" \ "US_BEGIN_NAMESPACE= namespace mitk {" \ "US_END_NAMESPACE=}" \ "US_BASECLASS_NAME=itk::LightObject" \ US_EXPORT= \ "DEPRECATED(func)=func" # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. For each # tag file the location of the external documentation should be added. The # format of a tag file without this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths # or URLs. Note that each tag file must have a unique name (where the name does # NOT include the path). If a tag file is not located in the directory in which # doxygen is run, you must also specify the path to the tagfile here. -TAGFILES = @BLUEBERRY_DOXYGEN_TAGFILE@ +TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = @MITK_DOXYGEN_TAGFILE_NAME@ # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = NO # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = @HAVE_DOT@ # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = @MITK_DOXYGEN_DOT_NUM_THREADS@ # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = FreeSans.ttf # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = @MITK_DOXYGEN_UML_LOOK@ # If the UML_LOOK tag is enabled, the fields and methods are shown inside # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more # managable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = NO # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = NO # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = @DOXYGEN_DOT_PATH@ # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES diff --git a/Documentation/Doxygen/ExampleCode/DocumentationExample.h b/Examples/DocumentationExample.h similarity index 100% rename from Documentation/Doxygen/ExampleCode/DocumentationExample.h rename to Examples/DocumentationExample.h diff --git a/Examples/Plugins/PluginList.cmake b/Examples/Plugins/PluginList.cmake index b29ba56832..ceb74aedde 100644 --- a/Examples/Plugins/PluginList.cmake +++ b/Examples/Plugins/PluginList.cmake @@ -1,14 +1,15 @@ # Plug-ins must be ordered according to their dependencies set(MITK_EXAMPLE_PLUGINS org.mitk.example.gui.minimalapplication:ON org.mitk.example.gui.customviewer:ON org.mitk.example.gui.customviewer.views:ON org.mitk.example.gui.multipleperspectives:ON org.mitk.example.gui.selectionserviceqt:ON org.mitk.example.gui.selectionservicemitk:ON org.mitk.example.gui.selectionservicemitk.views:ON org.mitk.example.gui.extensionpointdefinition:ON org.mitk.example.gui.extensionpointcontribution:ON + org.mitk.example.gui.regiongrowing:ON ) diff --git a/Plugins/org.mitk.gui.InteractionTests/CMakeLists.txt b/Examples/Plugins/org.mitk.example.gui.regiongrowing/CMakeLists.txt similarity index 53% rename from Plugins/org.mitk.gui.InteractionTests/CMakeLists.txt rename to Examples/Plugins/org.mitk.example.gui.regiongrowing/CMakeLists.txt index 60181330b7..315f17997a 100644 --- a/Plugins/org.mitk.gui.InteractionTests/CMakeLists.txt +++ b/Examples/Plugins/org.mitk.example.gui.regiongrowing/CMakeLists.txt @@ -1,7 +1,7 @@ -project(org_mitk_gui_InteractionTests) +project(org_mitk_example_gui_regiongrowing) MACRO_CREATE_MITK_CTK_PLUGIN( - EXPORT_DIRECTIVE INTERACTIONTESTS_EXPORT + EXPORT_DIRECTIVE REGIONGROWING_EXPORT EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDENCIES QmitkExt ) diff --git a/Examples/Plugins/org.mitk.example.gui.regiongrowing/documentation/doxygen/modules.dox b/Examples/Plugins/org.mitk.example.gui.regiongrowing/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..fd239e49c5 --- /dev/null +++ b/Examples/Plugins/org.mitk.example.gui.regiongrowing/documentation/doxygen/modules.dox @@ -0,0 +1,16 @@ +/** + \defgroup org_mitk_example_gui_regiongrowing org.mitk.example.gui.regiongrowing + \ingroup MITKExamplePlugins + + \brief Describe your plugin here. + +*/ + +/** + \defgroup org_mitk_example_gui_regiongrowing_internal Internal + \ingroup org_mitk_example_gui_regiongrowing + + \brief This subcategory includes the internal classes of the org.mitk.example.gui.regiongrowing plugin. Other + plugins must not rely on these classes. They contain implementation details and their interface + may change at any time. We mean it. +*/ diff --git a/Plugins/org.mitk.gui.InteractionTests/files.cmake b/Examples/Plugins/org.mitk.example.gui.regiongrowing/files.cmake similarity index 73% rename from Plugins/org.mitk.gui.InteractionTests/files.cmake rename to Examples/Plugins/org.mitk.example.gui.regiongrowing/files.cmake index ff5dcd2c35..527fc948cc 100644 --- a/Plugins/org.mitk.gui.InteractionTests/files.cmake +++ b/Examples/Plugins/org.mitk.example.gui.regiongrowing/files.cmake @@ -1,46 +1,42 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES - org_mitk_gui_InteractionTests_Activator.cpp - InteractionTests.cpp + org_mitk_example_gui_regiongrowing_Activator.cpp + QmitkRegionGrowingView.cpp ) set(UI_FILES - src/internal/InteractionTestsControls.ui + src/internal/QmitkRegionGrowingViewControls.ui ) set(MOC_H_FILES - src/internal/org_mitk_gui_InteractionTests_Activator.h - src/internal/InteractionTests.h + src/internal/org_mitk_example_gui_regiongrowing_Activator.h + src/internal/QmitkRegionGrowingView.h ) # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench set(CACHED_RESOURCE_FILES resources/icon.xpm plugin.xml ) # list of Qt .qrc files which contain additional resources # specific to this plugin set(QRC_FILES ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) - -set(RESOURCE_FILES -PointsConfigRightClick.xml -) diff --git a/Plugins/org.mitk.gui.InteractionTests/manifest_headers.cmake b/Examples/Plugins/org.mitk.example.gui.regiongrowing/manifest_headers.cmake similarity index 51% rename from Plugins/org.mitk.gui.InteractionTests/manifest_headers.cmake rename to Examples/Plugins/org.mitk.example.gui.regiongrowing/manifest_headers.cmake index 5fc129013f..6698c3c0ec 100644 --- a/Plugins/org.mitk.gui.InteractionTests/manifest_headers.cmake +++ b/Examples/Plugins/org.mitk.example.gui.regiongrowing/manifest_headers.cmake @@ -1,5 +1,5 @@ -set(Plugin-Name "InteractionTests") +set(Plugin-Name "Region Grower Example") set(Plugin-Version "0.1") set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") set(Plugin-ContactAddress "") -set(Require-Plugin org.mitk.gui.qt.common org.mitk.gui.qt.common.legacy) +set(Require-Plugin org.mitk.gui.qt.common) diff --git a/Plugins/org.mitk.gui.InteractionTests/plugin.xml b/Examples/Plugins/org.mitk.example.gui.regiongrowing/plugin.xml similarity index 51% rename from Plugins/org.mitk.gui.InteractionTests/plugin.xml rename to Examples/Plugins/org.mitk.example.gui.regiongrowing/plugin.xml index 9ad93e2b56..2ce18af7c8 100644 --- a/Plugins/org.mitk.gui.InteractionTests/plugin.xml +++ b/Examples/Plugins/org.mitk.example.gui.regiongrowing/plugin.xml @@ -1,9 +1,11 @@ + - - \ No newline at end of file + + diff --git a/Plugins/org.mitk.gui.InteractionTests/documentation/UserManual/icon.xpm b/Examples/Plugins/org.mitk.example.gui.regiongrowing/resources/icon.xpm similarity index 100% rename from Plugins/org.mitk.gui.InteractionTests/documentation/UserManual/icon.xpm rename to Examples/Plugins/org.mitk.example.gui.regiongrowing/resources/icon.xpm diff --git a/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/QmitkRegionGrowingView.cpp b/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/QmitkRegionGrowingView.cpp new file mode 100644 index 0000000000..fd5e271e72 --- /dev/null +++ b/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/QmitkRegionGrowingView.cpp @@ -0,0 +1,240 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +// Blueberry +#include +#include + +// Qmitk +#include "QmitkRegionGrowingView.h" + +//! [cpp-includes] +// Qmitk +#include "QmitkPointListWidget.h" +#include "QmitkRenderWindow.h" + +// MITK +#include "mitkImageAccessByItk.h" +#include "mitkITKImageImport.h" +#include "mitkProperties.h" +#include "mitkColorProperty.h" + +// ITK +#include +//! [cpp-includes] + +// Qt +#include + + +const std::string QmitkRegionGrowingView::VIEW_ID = "org.mitk.views.example.regiongrowing"; + +QmitkRegionGrowingView::QmitkRegionGrowingView() + : m_PointListWidget(NULL) +{ +} + +void QmitkRegionGrowingView::SetFocus() +{ + m_Controls.buttonPerformImageProcessing->setFocus(); +} + +void QmitkRegionGrowingView::CreateQtPartControl( QWidget *parent ) +{ + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi( parent ); + connect( m_Controls.buttonPerformImageProcessing, SIGNAL(clicked()), this, SLOT(DoImageProcessing()) ); + + //! [cpp-createqtpartcontrol] + // create a QmitkPointListWidget and add it to the widget created from .ui file + m_PointListWidget = new QmitkPointListWidget(); + m_Controls.verticalLayout->addWidget(m_PointListWidget, 1); + + // retrieve a possibly existing IRenderWindowPart + if (mitk::IRenderWindowPart* renderWindowPart = GetRenderWindowPart()) + { + // let the point set widget know about the render window part (crosshair updates) + RenderWindowPartActivated(renderWindowPart); + } + + // create a new DataNode containing a PointSet with some interaction + m_PointSet = mitk::PointSet::New(); + mitk::DataNode::Pointer pointSetNode = mitk::DataNode::New(); + pointSetNode->SetData( m_PointSet ); + pointSetNode->SetName("seed points for region growing"); + pointSetNode->SetProperty("helper object", mitk::BoolProperty::New(true) ); + pointSetNode->SetProperty("layer", mitk::IntProperty::New(1024) ); + + // add the pointset to the data storage (for rendering and access by other modules) + GetDataStorage()->Add( pointSetNode ); + + // tell the GUI widget about the point set + m_PointListWidget->SetPointSetNode( pointSetNode ); + //! [cpp-createqtpartcontrol] +} + +void QmitkRegionGrowingView::OnSelectionChanged( berry::IWorkbenchPart::Pointer /*source*/, + const QList& nodes ) +{ + // iterate all selected objects, adjust warning visibility + foreach( mitk::DataNode::Pointer node, nodes ) + { + if( node.IsNotNull() && dynamic_cast(node->GetData()) ) + { + m_Controls.labelWarning->setVisible( false ); + m_Controls.buttonPerformImageProcessing->setEnabled( true ); + return; + } + } + + m_Controls.labelWarning->setVisible( true ); + m_Controls.buttonPerformImageProcessing->setEnabled( false ); +} + +void QmitkRegionGrowingView::RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart) +{ + // let the point set widget know about the slice navigation controllers + // in the active render window part (crosshair updates) + foreach(QmitkRenderWindow* renderWindow, renderWindowPart->GetQmitkRenderWindows().values()) + { + m_PointListWidget->AddSliceNavigationController(renderWindow->GetSliceNavigationController()); + } +} + +void QmitkRegionGrowingView::RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart) +{ + foreach(QmitkRenderWindow* renderWindow, renderWindowPart->GetQmitkRenderWindows().values()) + { + m_PointListWidget->RemoveSliceNavigationController(renderWindow->GetSliceNavigationController()); + } +} + +void QmitkRegionGrowingView::DoImageProcessing() +{ + QList nodes = this->GetDataManagerSelection(); + if (nodes.empty()) return; + + mitk::DataNode* node = nodes.front(); + + if (!node) + { + // Nothing selected. Inform the user and return + QMessageBox::information( NULL, "Template", "Please load and select an image before starting image processing."); + return; + } + + // here we have a valid mitk::DataNode + + // a node itself is not very useful, we need its data item (the image) + mitk::BaseData* data = node->GetData(); + if (data) + { + // test if this data item is an image or not (could also be a surface or something totally different) + mitk::Image* image = dynamic_cast( data ); + if (image) + { + //! [cpp-doimageprocessing] + // So we have an image. Let's see if the user has set some seed points already + if (m_PointSet->GetSize() == 0) + { + // no points there. Not good for region growing + QMessageBox::information( NULL, + "Region growing functionality", + "Please set some seed points inside the image first.\n" + "(hold Shift key and click left mouse button inside the image.)" + ); + return; + } + + // actually perform region growing. Here we have both an image and some seed points + AccessByItk_1( image, ItkImageProcessing, image->GetGeometry() ) // some magic to call the correctly templated function + //! [cpp-doimageprocessing] + } + } +} + +//! [cpp-itkimageaccess] +template < typename TPixel, unsigned int VImageDimension > +void QmitkRegionGrowingView::ItkImageProcessing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry ) +{ + typedef itk::Image< TPixel, VImageDimension > InputImageType; + typedef typename InputImageType::IndexType IndexType; + + // instantiate an ITK region growing filter, set its parameters + typedef itk::ConnectedThresholdImageFilter RegionGrowingFilterType; + typename RegionGrowingFilterType::Pointer regionGrower = RegionGrowingFilterType::New(); + regionGrower->SetInput( itkImage ); // don't forget this + + // determine a thresholding interval + IndexType seedIndex; + TPixel min( std::numeric_limits::max() ); + TPixel max( std::numeric_limits::min() ); + mitk::PointSet::PointsContainer* points = m_PointSet->GetPointSet()->GetPoints(); + for ( mitk::PointSet::PointsConstIterator pointsIterator = points->Begin(); + pointsIterator != points->End(); + ++pointsIterator ) + { + // first test if this point is inside the image at all + if ( !imageGeometry->IsInside( pointsIterator.Value()) ) + { + continue; + } + + // convert world coordinates to image indices + imageGeometry->WorldToIndex( pointsIterator.Value(), seedIndex); + + // get the pixel value at this point + TPixel currentPixelValue = itkImage->GetPixel( seedIndex ); + + // adjust minimum and maximum values + if (currentPixelValue > max) + max = currentPixelValue; + + if (currentPixelValue < min) + min = currentPixelValue; + + regionGrower->AddSeed( seedIndex ); + } + + MITK_INFO << "Values between " << min << " and " << max; + + min -= 30; + max += 30; + + // set thresholds and execute filter + regionGrower->SetLower( min ); + regionGrower->SetUpper( max ); + + regionGrower->Update(); + + mitk::Image::Pointer resultImage = mitk::ImportItkImage( regionGrower->GetOutput() ); + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + newNode->SetData( resultImage ); + + // set some properties + newNode->SetProperty("binary", mitk::BoolProperty::New(true)); + newNode->SetProperty("name", mitk::StringProperty::New("dumb segmentation")); + newNode->SetProperty("color", mitk::ColorProperty::New(1.0,0.0,0.0)); + newNode->SetProperty("volumerendering", mitk::BoolProperty::New(true)); + newNode->SetProperty("layer", mitk::IntProperty::New(1)); + newNode->SetProperty("opacity", mitk::FloatProperty::New(0.5)); + + // add result to data tree + this->GetDataStorage()->Add( newNode ); + mitk::RenderingManager::GetInstance()->RequestUpdateAll(); +} +//! [cpp-itkimageaccess] diff --git a/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/QmitkRegionGrowingView.h b/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/QmitkRegionGrowingView.h new file mode 100644 index 0000000000..2f5c998088 --- /dev/null +++ b/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/QmitkRegionGrowingView.h @@ -0,0 +1,97 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef QmitkRegionGrowingView_h +#define QmitkRegionGrowingView_h + +#include + +#include + +#include "ui_QmitkRegionGrowingViewControls.h" + +//! [includes] +#include "mitkPointSet.h" +#include "mitkIRenderWindowPartListener.h" + +class QmitkPointListWidget; +//! [includes] + +/** + \brief QmitkRegionGrowingView + + \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. + + \sa QmitkAbstractView + \ingroup ${plugin_target}_internal +*/ +class QmitkRegionGrowingView : public QmitkAbstractView, public mitk::IRenderWindowPartListener +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + + public: + + static const std::string VIEW_ID; + + QmitkRegionGrowingView(); + + protected slots: + + /// \brief Called when the user clicks the GUI button + void DoImageProcessing(); + + protected: + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void SetFocus(); + + /// \brief called by QmitkFunctionality when DataManager's selection has changed + virtual void OnSelectionChanged( berry::IWorkbenchPart::Pointer source, + const QList& nodes ); + + //! [render-window-part-listener] + void RenderWindowPartActivated(mitk::IRenderWindowPart* renderWindowPart); + void RenderWindowPartDeactivated(mitk::IRenderWindowPart* renderWindowPart); + //! [render-window-part-listener] + + Ui::QmitkRegionGrowingViewControls m_Controls; + + private: + + //! [itkimageprocessing] + /** + \brief ITK image processing function + This function is templated like an ITK image. The MITK-Macro AccessByItk determines the actual pixel type and dimensionality of + a given MITK image and calls this function for further processing (in our case region growing) + */ + template < typename TPixel, unsigned int VImageDimension > + void ItkImageProcessing( itk::Image< TPixel, VImageDimension >* itkImage, mitk::Geometry3D* imageGeometry ); + //! [itkimageprocessing] + + //! [members] + /// \brief This is the actual seed point data object + mitk::PointSet::Pointer m_PointSet; + + QmitkPointListWidget* m_PointListWidget; + //! [members] + +}; + +#endif // QmitkRegionGrowingView_h diff --git a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTestsControls.ui b/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/QmitkRegionGrowingViewControls.ui similarity index 52% rename from Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTestsControls.ui rename to Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/QmitkRegionGrowingViewControls.ui index f1ced7fe57..af93c6a8aa 100644 --- a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTestsControls.ui +++ b/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/QmitkRegionGrowingViewControls.ui @@ -1,78 +1,48 @@ - InteractionTestsControls - + QmitkRegionGrowingViewControls + 0 0 - 234 + 222 161 0 0 QmitkTemplate QLabel { color: rgb(255, 0, 0) } Please select an image! - + Do image processing - Line Interactor + Do Something - - - - Toggle Config of Selected - - - - - - - Line Interactor (Grab Input) - - - - - - - Qt::Vertical - - - QSizePolicy::Expanding - - - - 20 - 220 - - - - diff --git a/Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.cpp b/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/org_mitk_example_gui_regiongrowing_Activator.cpp similarity index 57% rename from Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.cpp rename to Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/org_mitk_example_gui_regiongrowing_Activator.cpp index 75e26a9aea..a0d3863e2e 100644 --- a/Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.cpp +++ b/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/org_mitk_example_gui_regiongrowing_Activator.cpp @@ -1,38 +1,38 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "org_mitk_gui_InteractionTests_Activator.h" +#include "org_mitk_example_gui_regiongrowing_Activator.h" #include -#include "InteractionTests.h" +#include "QmitkRegionGrowingView.h" namespace mitk { -void org_mitk_gui_InteractionTests_Activator::start(ctkPluginContext* context) +void org_mitk_example_gui_regiongrowing_Activator::start(ctkPluginContext* context) { - BERRY_REGISTER_EXTENSION_CLASS(InteractionTests, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkRegionGrowingView, context) } -void org_mitk_gui_InteractionTests_Activator::stop(ctkPluginContext* context) +void org_mitk_example_gui_regiongrowing_Activator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } -Q_EXPORT_PLUGIN2(org_mitk_gui_InteractionTests, mitk::org_mitk_gui_InteractionTests_Activator) +Q_EXPORT_PLUGIN2(org_mitk_example_gui_regiongrowing, mitk::org_mitk_example_gui_regiongrowing_Activator) diff --git a/Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.h b/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/org_mitk_example_gui_regiongrowing_Activator.h similarity index 73% rename from Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.h rename to Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/org_mitk_example_gui_regiongrowing_Activator.h index bc6fcc4e66..29d561d6f5 100644 --- a/Plugins/org.mitk.gui.InteractionTests/src/internal/org_mitk_gui_InteractionTests_Activator.h +++ b/Examples/Plugins/org.mitk.example.gui.regiongrowing/src/internal/org_mitk_example_gui_regiongrowing_Activator.h @@ -1,40 +1,40 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#ifndef org_mitk_gui_InteractionTests_Activator_h -#define org_mitk_gui_InteractionTests_Activator_h +#ifndef org_mitk_example_gui_regiongrowing_Activator_h +#define org_mitk_example_gui_regiongrowing_Activator_h #include namespace mitk { -class org_mitk_gui_InteractionTests_Activator : +class org_mitk_example_gui_regiongrowing_Activator : public QObject, public ctkPluginActivator { Q_OBJECT Q_INTERFACES(ctkPluginActivator) public: void start(ctkPluginContext* context); void stop(ctkPluginContext* context); -}; // org_mitk_gui_InteractionTests_Activator +}; // org_mitk_example_gui_regiongrowing_Activator } -#endif // org_mitk_gui_InteractionTests_Activator_h +#endif // org_mitk_example_gui_regiongrowing_Activator_h diff --git a/Examples/QtFreeRender/QtFreeRender.cpp b/Examples/QtFreeRender/QtFreeRender.cpp index 421c89fa8e..3149c7cbb4 100644 --- a/Examples/QtFreeRender/QtFreeRender.cpp +++ b/Examples/QtFreeRender/QtFreeRender.cpp @@ -1,385 +1,373 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRenderWindow.h" #include #include #include #include #include #include #include #include "mitkProperties.h" #include "mitkGeometry2DDataMapper2D.h" #include "mitkGlobalInteraction.h" #include "mitkDisplayInteractor.h" #include "mitkPositionEvent.h" #include "mitkStateEvent.h" #include "mitkLine.h" #include "mitkInteractionConst.h" #include "mitkVtkLayerController.h" #include "mitkPositionTracker.h" #include "mitkDisplayInteractor.h" #include "mitkSlicesRotator.h" #include "mitkSlicesSwiveller.h" #include "mitkRenderWindowFrame.h" #include "mitkGradientBackground.h" #include "mitkCoordinateSupplier.h" #include "mitkDataStorage.h" #include "vtkTextProperty.h" #include "vtkCornerAnnotation.h" #include "vtkRenderWindow.h" #include "vtkRenderWindowInteractor.h" #include "vtkAnnotatedCubeActor.h" #include "vtkOrientationMarkerWidget.h" #include "vtkProperty.h" // us #include "mitkGetModuleContext.h" #include "mitkModule.h" #include "mitkModuleRegistry.h" -#include "mitkInformer.h" +#include "mitkInteractionEventObserver.h" //##Documentation //## @brief Example of a NON QT DEPENDENT MITK RENDERING APPLICATION. mitk::RenderWindow::Pointer mitkWidget1; mitk::RenderWindow::Pointer mitkWidget2; mitk::RenderWindow::Pointer mitkWidget3; mitk::RenderWindow::Pointer mitkWidget4; mitk::DisplayInteractor::Pointer m_DisplayInteractor; mitk::CoordinateSupplier::Pointer m_LastLeftClickPositionSupplier; mitk::GradientBackground::Pointer m_GradientBackground4; mitk::RenderWindowFrame::Pointer m_RectangleRendering1; mitk::RenderWindowFrame::Pointer m_RectangleRendering2; mitk::RenderWindowFrame::Pointer m_RectangleRendering3; mitk::RenderWindowFrame::Pointer m_RectangleRendering4; mitk::SliceNavigationController* m_TimeNavigationController = NULL; mitk::DataStorage::Pointer m_DataStorage; mitk::DataNode::Pointer m_PlaneNode1; mitk::DataNode::Pointer m_PlaneNode2; mitk::DataNode::Pointer m_PlaneNode3; mitk::DataNode::Pointer m_Node; void InitializeWindows() { // Set default view directions for SNCs mitkWidget1->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Axial); mitkWidget2->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Sagittal); mitkWidget3->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Frontal); mitkWidget4->GetSliceNavigationController()->SetDefaultViewDirection(mitk::SliceNavigationController::Original); //initialize m_TimeNavigationController: send time via sliceNavigationControllers m_TimeNavigationController = mitk::RenderingManager::GetInstance()->GetTimeNavigationController(); m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget1->GetSliceNavigationController(), false); m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget2->GetSliceNavigationController(), false); m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget3->GetSliceNavigationController(), false); m_TimeNavigationController->ConnectGeometryTimeEvent(mitkWidget4->GetSliceNavigationController(), false); mitkWidget1->GetSliceNavigationController()->ConnectGeometrySendEvent(mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow())); //reverse connection between sliceNavigationControllers and m_TimeNavigationController mitkWidget1->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); mitkWidget2->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); mitkWidget3->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); mitkWidget4->GetSliceNavigationController()->ConnectGeometryTimeEvent(m_TimeNavigationController, false); // Let NavigationControllers listen to GlobalInteraction mitk::GlobalInteraction *gi = mitk::GlobalInteraction::GetInstance(); gi->AddListener(m_TimeNavigationController); m_LastLeftClickPositionSupplier = mitk::CoordinateSupplier::New("navigation", NULL); mitk::GlobalInteraction::GetInstance()->AddListener(m_LastLeftClickPositionSupplier); m_GradientBackground4 = mitk::GradientBackground::New(); m_GradientBackground4->SetRenderWindow(mitkWidget4->GetVtkRenderWindow()); m_GradientBackground4->SetGradientColors(0.1, 0.1, 0.1, 0.5, 0.5, 0.5); m_GradientBackground4->Enable(); m_RectangleRendering1 = mitk::RenderWindowFrame::New(); m_RectangleRendering1->SetRenderWindow(mitkWidget1->GetVtkRenderWindow()); m_RectangleRendering1->Enable(1.0, 0.0, 0.0); m_RectangleRendering2 = mitk::RenderWindowFrame::New(); m_RectangleRendering2->SetRenderWindow(mitkWidget2->GetVtkRenderWindow()); m_RectangleRendering2->Enable(0.0, 1.0, 0.0); m_RectangleRendering3 = mitk::RenderWindowFrame::New(); m_RectangleRendering3->SetRenderWindow(mitkWidget3->GetVtkRenderWindow()); m_RectangleRendering3->Enable(0.0, 0.0, 1.0); m_RectangleRendering4 = mitk::RenderWindowFrame::New(); m_RectangleRendering4->SetRenderWindow(mitkWidget4->GetVtkRenderWindow()); m_RectangleRendering4->Enable(1.0, 1.0, 0.0); } void AddDisplayPlaneSubTree() { // add the displayed planes of the multiwidget to a node to which the subtree // @a planesSubTree points ... float white[3] = { 1.0f, 1.0f, 1.0f }; mitk::Geometry2DDataMapper2D::Pointer mapper; mitk::IntProperty::Pointer layer = mitk::IntProperty::New(1000); // ... of widget 1 m_PlaneNode1 = (mitk::BaseRenderer::GetInstance(mitkWidget1->GetVtkRenderWindow()))->GetCurrentWorldGeometry2DNode(); m_PlaneNode1->SetColor(white, mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow())); m_PlaneNode1->SetProperty("visible", mitk::BoolProperty::New(true)); m_PlaneNode1->SetProperty("name", mitk::StringProperty::New("widget1Plane")); m_PlaneNode1->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); m_PlaneNode1->SetProperty("helper object", mitk::BoolProperty::New(true)); m_PlaneNode1->SetProperty("layer", layer); m_PlaneNode1->SetColor(1.0, 0.0, 0.0); mapper = mitk::Geometry2DDataMapper2D::New(); m_PlaneNode1->SetMapper(mitk::BaseRenderer::Standard2D, mapper); // ... of widget 2 m_PlaneNode2 = (mitk::BaseRenderer::GetInstance(mitkWidget2->GetVtkRenderWindow()))->GetCurrentWorldGeometry2DNode(); m_PlaneNode2->SetColor(white, mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow())); m_PlaneNode2->SetProperty("visible", mitk::BoolProperty::New(true)); m_PlaneNode2->SetProperty("name", mitk::StringProperty::New("widget2Plane")); m_PlaneNode2->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); m_PlaneNode2->SetProperty("helper object", mitk::BoolProperty::New(true)); m_PlaneNode2->SetProperty("layer", layer); m_PlaneNode2->SetColor(0.0, 1.0, 0.0); mapper = mitk::Geometry2DDataMapper2D::New(); m_PlaneNode2->SetMapper(mitk::BaseRenderer::Standard2D, mapper); // ... of widget 3 m_PlaneNode3 = (mitk::BaseRenderer::GetInstance(mitkWidget3->GetVtkRenderWindow()))->GetCurrentWorldGeometry2DNode(); m_PlaneNode3->SetColor(white, mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow())); m_PlaneNode3->SetProperty("visible", mitk::BoolProperty::New(true)); m_PlaneNode3->SetProperty("name", mitk::StringProperty::New("widget3Plane")); m_PlaneNode3->SetProperty("includeInBoundingBox", mitk::BoolProperty::New(false)); m_PlaneNode3->SetProperty("helper object", mitk::BoolProperty::New(true)); m_PlaneNode3->SetProperty("layer", layer); m_PlaneNode3->SetColor(0.0, 0.0, 1.0); mapper = mitk::Geometry2DDataMapper2D::New(); m_PlaneNode3->SetMapper(mitk::BaseRenderer::Standard2D, mapper); m_Node = mitk::DataNode::New(); m_Node->SetProperty("name", mitk::StringProperty::New("Widgets")); m_Node->SetProperty("helper object", mitk::BoolProperty::New(true)); //AddPlanesToDataStorage if (m_PlaneNode1.IsNotNull() && m_PlaneNode2.IsNotNull() && m_PlaneNode3.IsNotNull() && m_Node.IsNotNull()) { if (m_DataStorage.IsNotNull()) { m_DataStorage->Add(m_Node); m_DataStorage->Add(m_PlaneNode1, m_Node); m_DataStorage->Add(m_PlaneNode2, m_Node); m_DataStorage->Add(m_PlaneNode3, m_Node); static_cast(m_PlaneNode1->GetMapper(mitk::BaseRenderer::Standard2D))->SetDatastorageAndGeometryBaseNode( m_DataStorage, m_Node); static_cast(m_PlaneNode2->GetMapper(mitk::BaseRenderer::Standard2D))->SetDatastorageAndGeometryBaseNode( m_DataStorage, m_Node); static_cast(m_PlaneNode3->GetMapper(mitk::BaseRenderer::Standard2D))->SetDatastorageAndGeometryBaseNode( m_DataStorage, m_Node); } } } void Fit() { vtkRenderer * vtkrenderer; mitk::BaseRenderer::GetInstance(mitkWidget1->GetVtkRenderWindow())->GetDisplayGeometry()->Fit(); mitk::BaseRenderer::GetInstance(mitkWidget2->GetVtkRenderWindow())->GetDisplayGeometry()->Fit(); mitk::BaseRenderer::GetInstance(mitkWidget3->GetVtkRenderWindow())->GetDisplayGeometry()->Fit(); mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow())->GetDisplayGeometry()->Fit(); int w = vtkObject::GetGlobalWarningDisplay(); vtkObject::GlobalWarningDisplayOff(); vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget1->GetVtkRenderWindow())->GetVtkRenderer(); if (vtkrenderer != NULL) vtkrenderer->ResetCamera(); vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget2->GetVtkRenderWindow())->GetVtkRenderer(); if (vtkrenderer != NULL) vtkrenderer->ResetCamera(); vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget3->GetVtkRenderWindow())->GetVtkRenderer(); if (vtkrenderer != NULL) vtkrenderer->ResetCamera(); vtkrenderer = mitk::BaseRenderer::GetInstance(mitkWidget4->GetVtkRenderWindow())->GetVtkRenderer(); if (vtkrenderer != NULL) vtkrenderer->ResetCamera(); vtkObject::SetGlobalWarningDisplay(w); } int main(int argc, char* argv[]) { if (argc < 2) { fprintf(stderr, "Usage: %s [filename1] [filename2] ...\n\n", ""); return 1; } // Create a DataStorage m_DataStorage = mitk::StandaloneDataStorage::New(); //************************************************************************* // Part II: Create some data by reading files //************************************************************************* int i; for (i = 1; i < argc; ++i) { // For testing if (strcmp(argv[i], "-testing") == 0) continue; // Create a DataNodeFactory to read a data format supported // by the DataNodeFactory (many image formats, surface formats, etc.) mitk::DataNodeFactory::Pointer nodeReader = mitk::DataNodeFactory::New(); const char * filename = argv[i]; try { nodeReader->SetFileName(filename); nodeReader->Update(); // Since the DataNodeFactory directly creates a node, // use the datastorage to add the read node mitk::DataNode::Pointer node = nodeReader->GetOutput(); m_DataStorage->Add(node); mitk::Image::Pointer image = dynamic_cast(node->GetData()); if (image.IsNotNull()) { // Set the property "volumerendering" to the Boolean value "true" node->SetProperty("volumerendering", mitk::BoolProperty::New(false)); node->SetProperty("name", mitk::StringProperty::New("testimage")); node->SetProperty("layer", mitk::IntProperty::New(1)); } } catch (...) { fprintf(stderr, "Could not open file %s \n\n", filename); exit(2); } } //************************************************************************* // Part V: Create window and pass the tree to it //************************************************************************* // Global Interaction initialize // legacy because window manager relies still on existence if global interaction mitk::GlobalInteraction::GetInstance()->Initialize("global"); //mitk::GlobalInteraction::GetInstance()->AddListener(m_DisplayInteractor); // Create renderwindows mitkWidget1 = mitk::RenderWindow::New(); mitkWidget2 = mitk::RenderWindow::New(); mitkWidget3 = mitk::RenderWindow::New(); mitkWidget4 = mitk::RenderWindow::New(); // Tell the renderwindow which (part of) the datastorage to render mitkWidget1->GetRenderer()->SetDataStorage(m_DataStorage); mitkWidget2->GetRenderer()->SetDataStorage(m_DataStorage); mitkWidget3->GetRenderer()->SetDataStorage(m_DataStorage); mitkWidget4->GetRenderer()->SetDataStorage(m_DataStorage); // Let NavigationControllers listen to GlobalInteraction mitk::GlobalInteraction *gi = mitk::GlobalInteraction::GetInstance(); gi->AddListener(mitkWidget1->GetSliceNavigationController()); gi->AddListener(mitkWidget2->GetSliceNavigationController()); gi->AddListener(mitkWidget3->GetSliceNavigationController()); gi->AddListener(mitkWidget4->GetSliceNavigationController()); // instantiate display interactor if (m_DisplayInteractor.IsNull()) { m_DisplayInteractor = mitk::DisplayInteractor::New(); m_DisplayInteractor->LoadStateMachine("DisplayInteraction.xml"); m_DisplayInteractor->LoadEventConfig("DisplayConfigMITK.xml"); - // Register as listener + // Register as listener via micro services + mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); - if (context != NULL) - { - mitk::ServiceReference serviceRef = context->GetServiceReference(); - mitk::InformerService* service = dynamic_cast(context->GetService(serviceRef)); - if (serviceRef != NULL) - { - service->RegisterObserver(m_DisplayInteractor.GetPointer()); - } else { - MITK_ERROR << "Service not registered."; - } - } - else - { - MITK_ERROR<< "Invalid Module context."; - } + context->RegisterService( + m_DisplayInteractor.GetPointer()); } // Use it as a 2D View mitkWidget1->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D); mitkWidget2->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D); mitkWidget3->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard2D); mitkWidget4->GetRenderer()->SetMapperID(mitk::BaseRenderer::Standard3D); mitkWidget1->SetSize(400, 400); mitkWidget2->GetVtkRenderWindow()->SetPosition(mitkWidget1->GetVtkRenderWindow()->GetPosition()[0] + 420, mitkWidget1->GetVtkRenderWindow()->GetPosition()[1]); mitkWidget2->SetSize(400, 400); mitkWidget3->GetVtkRenderWindow()->SetPosition(mitkWidget1->GetVtkRenderWindow()->GetPosition()[0], mitkWidget1->GetVtkRenderWindow()->GetPosition()[1] + 450); mitkWidget3->SetSize(400, 400); mitkWidget4->GetVtkRenderWindow()->SetPosition(mitkWidget1->GetVtkRenderWindow()->GetPosition()[0] + 420, mitkWidget1->GetVtkRenderWindow()->GetPosition()[1] + 450); mitkWidget4->SetSize(400, 400); InitializeWindows(); AddDisplayPlaneSubTree(); Fit(); // Initialize the RenderWindows mitk::TimeSlicedGeometry::Pointer geo = m_DataStorage->ComputeBoundingGeometry3D(m_DataStorage->GetAll()); mitk::RenderingManager::GetInstance()->InitializeViews(geo); m_DataStorage->Print(std::cout); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // reinit the mitkVTKEventProvider; // this is only necessary once after calling // ForceImmediateUpdateAll() for the first time mitkWidget1->ReinitEventProvider(); mitkWidget2->ReinitEventProvider(); mitkWidget3->ReinitEventProvider(); mitkWidget1->GetVtkRenderWindow()->Render(); mitkWidget2->GetVtkRenderWindow()->Render(); mitkWidget3->GetVtkRenderWindow()->Render(); mitkWidget4->GetVtkRenderWindow()->Render(); mitkWidget4->GetVtkRenderWindowInteractor()->Start(); return 0; } diff --git a/Modules/DiffusionImaging/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.cpp b/Modules/DiffusionImaging/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.cpp index a857776901..c660e9d9e1 100644 --- a/Modules/DiffusionImaging/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.cpp +++ b/Modules/DiffusionImaging/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.cpp @@ -1,760 +1,756 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkConnectomicsNetworkMapper3D.h" #include #include "vtkGraphLayout.h" #include #include "vtkGraphToPolyData.h" #include #include "vtkGlyph3D.h" #include "vtkGlyphSource2D.h" #include "mitkConnectomicsRenderingProperties.h" #include "mitkConnectomicsRenderingSchemeProperty.h" #include "mitkConnectomicsRenderingEdgeFilteringProperty.h" #include "mitkConnectomicsRenderingNodeFilteringProperty.h" #include "mitkConnectomicsRenderingNodeColorParameterProperty.h" #include "mitkConnectomicsRenderingNodeRadiusParameterProperty.h" #include "mitkConnectomicsRenderingEdgeColorParameterProperty.h" #include "mitkConnectomicsRenderingEdgeRadiusParameterProperty.h" #include "mitkConnectomicsRenderingNodeThresholdParameterProperty.h" #include "mitkConnectomicsRenderingEdgeThresholdParameterProperty.h" #include mitk::ConnectomicsNetworkMapper3D::ConnectomicsNetworkMapper3D() { m_NetworkAssembly = vtkPropAssembly::New(); } mitk::ConnectomicsNetworkMapper3D:: ~ConnectomicsNetworkMapper3D() { m_NetworkAssembly->Delete(); } void mitk::ConnectomicsNetworkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) { if( this->GetInput() == NULL ) { return; } bool propertiesHaveChanged = this->PropertiesChanged(); if( this->GetInput()->GetIsModified( ) || propertiesHaveChanged ) { - GenerateData(); - } -} -void mitk::ConnectomicsNetworkMapper3D::GenerateData() -{ m_NetworkAssembly->Delete(); m_NetworkAssembly = vtkPropAssembly::New(); // Here is the part where a graph is given and converted to points and connections between points... std::vector< mitk::ConnectomicsNetwork::NetworkNode > vectorOfNodes = this->GetInput()->GetVectorOfAllNodes(); std::vector< std::pair< std::pair< mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode > , mitk::ConnectomicsNetwork::NetworkEdge > > vectorOfEdges = this->GetInput()->GetVectorOfAllEdges(); // Decide on the style of rendering due to property if( m_ChosenRenderingScheme == connectomicsRenderingMITKScheme ) { mitk::Point3D tempWorldPoint, tempCNFGeometryPoint; //////////////////////Prepare coloring and radius//////////// std::vector< double > vectorOfNodeRadiusParameterValues; vectorOfNodeRadiusParameterValues.resize( vectorOfNodes.size() ); double maxNodeRadiusParameterValue( FillNodeParameterVector( &vectorOfNodeRadiusParameterValues, m_NodeRadiusParameter ) ); std::vector< double > vectorOfNodeColorParameterValues; vectorOfNodeColorParameterValues.resize( vectorOfNodes.size() ); double maxNodeColorParameterValue( FillNodeParameterVector( &vectorOfNodeColorParameterValues, m_NodeColorParameter ) ); std::vector< double > vectorOfEdgeRadiusParameterValues; vectorOfEdgeRadiusParameterValues.resize( vectorOfEdges.size() ); double maxEdgeRadiusParameterValue( FillEdgeParameterVector( &vectorOfEdgeRadiusParameterValues, m_EdgeRadiusParameter ) ); std::vector< double > vectorOfEdgeColorParameterValues; vectorOfEdgeColorParameterValues.resize( vectorOfEdges.size() ); double maxEdgeColorParameterValue( FillEdgeParameterVector( &vectorOfEdgeColorParameterValues, m_EdgeColorParameter ) ); //////////////////////Prepare Filtering////////////////////// // true will be rendered std::vector< bool > vectorOfNodeFilterBools( vectorOfNodes.size(), true ); if( m_ChosenNodeFilter == connectomicsRenderingNodeThresholdingFilter ) { FillNodeFilterBoolVector( &vectorOfNodeFilterBools, m_NodeThresholdParameter ); } std::vector< bool > vectorOfEdgeFilterBools( vectorOfEdges.size(), true ); if( m_ChosenEdgeFilter == connectomicsRenderingEdgeThresholdFilter ) { FillEdgeFilterBoolVector( &vectorOfEdgeFilterBools, m_EdgeThresholdParameter ); } //////////////////////Create Spheres///////////////////////// for(unsigned int i = 0; i < vectorOfNodes.size(); i++) { vtkSmartPointer sphereSource = vtkSmartPointer::New(); for(unsigned int dimension = 0; dimension < 3; dimension++) { tempCNFGeometryPoint.SetElement( dimension , vectorOfNodes[i].coordinates[dimension] ); } - this->GetData()->GetGeometry()->IndexToWorld( tempCNFGeometryPoint, tempWorldPoint ); + GetDataNode()->GetData()->GetGeometry()->IndexToWorld( tempCNFGeometryPoint, tempWorldPoint ); sphereSource->SetCenter( tempWorldPoint[0] , tempWorldPoint[1], tempWorldPoint[2] ); // determine radius double radiusFactor = vectorOfNodeRadiusParameterValues[i] / maxNodeRadiusParameterValue; double radius = m_NodeRadiusStart + ( m_NodeRadiusEnd - m_NodeRadiusStart) * radiusFactor; sphereSource->SetRadius( radius ); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInput(sphereSource->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper); // determine color double colorFactor = vectorOfNodeColorParameterValues[i] / maxNodeColorParameterValue; double redStart = m_NodeColorStart.GetElement( 0 ); double greenStart = m_NodeColorStart.GetElement( 1 ); double blueStart = m_NodeColorStart.GetElement( 2 ); double redEnd = m_NodeColorEnd.GetElement( 0 ); double greenEnd = m_NodeColorEnd.GetElement( 1 ); double blueEnd = m_NodeColorEnd.GetElement( 2 ); double red = redStart + ( redEnd - redStart ) * colorFactor; double green = greenStart + ( greenEnd - greenStart ) * colorFactor; double blue = blueStart + ( blueEnd - blueStart ) * colorFactor; actor->GetProperty()->SetColor( red, green, blue); if( vectorOfNodeFilterBools[i] ) { m_NetworkAssembly->AddPart(actor); } } //////////////////////Create Tubes///////////////////////// double maxWeight = (double) this->GetInput()->GetMaximumWeight(); for(unsigned int i = 0; i < vectorOfEdges.size(); i++) { vtkSmartPointer lineSource = vtkSmartPointer::New(); for(unsigned int dimension = 0; dimension < 3; dimension++) { tempCNFGeometryPoint[ dimension ] = vectorOfEdges[i].first.first.coordinates[dimension]; } - this->GetData()->GetGeometry()->IndexToWorld( tempCNFGeometryPoint, tempWorldPoint ); + GetDataNode()->GetData()->GetGeometry()->IndexToWorld( tempCNFGeometryPoint, tempWorldPoint ); lineSource->SetPoint1(tempWorldPoint[0], tempWorldPoint[1],tempWorldPoint[2] ); for(unsigned int dimension = 0; dimension < 3; dimension++) { tempCNFGeometryPoint[ dimension ] = vectorOfEdges[i].first.second.coordinates[dimension]; } - this->GetData()->GetGeometry()->IndexToWorld( tempCNFGeometryPoint, tempWorldPoint ); + GetDataNode()->GetData()->GetGeometry()->IndexToWorld( tempCNFGeometryPoint, tempWorldPoint ); lineSource->SetPoint2(tempWorldPoint[0], tempWorldPoint[1], tempWorldPoint[2] ); vtkSmartPointer tubes = vtkSmartPointer::New(); tubes->SetInput( lineSource->GetOutput() ); tubes->SetNumberOfSides( 12 ); // determine radius double radiusFactor = vectorOfEdgeRadiusParameterValues[i] / maxEdgeRadiusParameterValue; double radius = m_EdgeRadiusStart + ( m_EdgeRadiusEnd - m_EdgeRadiusStart) * radiusFactor; tubes->SetRadius( radius ); // originally we used a logarithmic scaling, // double radiusFactor = 1.0 + ((double) vectorOfEdges[i].second.weight) / 10.0 ; // tubes->SetRadius( std::log10( radiusFactor ) ); vtkSmartPointer mapper2 = vtkSmartPointer::New(); mapper2->SetInput( tubes->GetOutput() ); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(mapper2); // determine color double colorFactor = vectorOfEdgeColorParameterValues[i] / maxEdgeColorParameterValue; double redStart = m_EdgeColorStart.GetElement( 0 ); double greenStart = m_EdgeColorStart.GetElement( 1 ); double blueStart = m_EdgeColorStart.GetElement( 2 ); double redEnd = m_EdgeColorEnd.GetElement( 0 ); double greenEnd = m_EdgeColorEnd.GetElement( 1 ); double blueEnd = m_EdgeColorEnd.GetElement( 2 ); double red = redStart + ( redEnd - redStart ) * colorFactor; double green = greenStart + ( greenEnd - greenStart ) * colorFactor; double blue = blueStart + ( blueEnd - blueStart ) * colorFactor; actor->GetProperty()->SetColor( red, green, blue); if( vectorOfEdgeFilterBools[i] ) { m_NetworkAssembly->AddPart(actor); } } } else if( m_ChosenRenderingScheme == connectomicsRenderingVTKScheme ) { vtkSmartPointer graph = vtkSmartPointer::New(); std::vector< vtkIdType > networkToVTKvector; networkToVTKvector.resize(vectorOfNodes.size()); for(unsigned int i = 0; i < vectorOfNodes.size(); i++) { networkToVTKvector[vectorOfNodes[i].id] = graph->AddVertex(); } for(unsigned int i = 0; i < vectorOfEdges.size(); i++) { graph->AddEdge(networkToVTKvector[vectorOfEdges[i].first.first.id], networkToVTKvector[vectorOfEdges[i].first.second.id]); } vtkSmartPointer points = vtkSmartPointer::New(); for(unsigned int i = 0; i < vectorOfNodes.size(); i++) { double x = vectorOfNodes[i].coordinates[0]; double y = vectorOfNodes[i].coordinates[1]; double z = vectorOfNodes[i].coordinates[2]; points->InsertNextPoint( x, y, z); } graph->SetPoints(points); vtkGraphLayout* layout = vtkGraphLayout::New(); layout->SetInput(graph); layout->SetLayoutStrategy(vtkPassThroughLayoutStrategy::New()); vtkGraphToPolyData* graphToPoly = vtkGraphToPolyData::New(); graphToPoly->SetInputConnection(layout->GetOutputPort()); // Create the standard VTK polydata mapper and actor // for the connections (edges) in the tree. vtkPolyDataMapper* edgeMapper = vtkPolyDataMapper::New(); edgeMapper->SetInputConnection(graphToPoly->GetOutputPort()); vtkActor* edgeActor = vtkActor::New(); edgeActor->SetMapper(edgeMapper); edgeActor->GetProperty()->SetColor(0.0, 0.5, 1.0); // Glyph the points of the tree polydata to create // VTK_VERTEX cells at each vertex in the tree. vtkGlyph3D* vertGlyph = vtkGlyph3D::New(); vertGlyph->SetInputConnection(0, graphToPoly->GetOutputPort()); vtkGlyphSource2D* glyphSource = vtkGlyphSource2D::New(); glyphSource->SetGlyphTypeToVertex(); vertGlyph->SetInputConnection(1, glyphSource->GetOutputPort()); // Create a mapper for the vertices, and tell the mapper // to use the specified color array. vtkPolyDataMapper* vertMapper = vtkPolyDataMapper::New(); vertMapper->SetInputConnection(vertGlyph->GetOutputPort()); /*if (colorArray) { vertMapper->SetScalarModeToUsePointFieldData(); vertMapper->SelectColorArray(colorArray); vertMapper->SetScalarRange(colorRange); }*/ // Create an actor for the vertices. Move the actor forward // in the z direction so it is drawn on top of the edge actor. vtkActor* vertActor = vtkActor::New(); vertActor->SetMapper(vertMapper); vertActor->GetProperty()->SetPointSize(5); vertActor->SetPosition(0, 0, 0.001); m_NetworkAssembly->AddPart(edgeActor); m_NetworkAssembly->AddPart(vertActor); } - (static_cast ( GetData() ) )->SetIsModified( false ); + (static_cast ( GetDataNode()->GetData() ) )->SetIsModified( false ); + } } const mitk::ConnectomicsNetwork* mitk::ConnectomicsNetworkMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } void mitk::ConnectomicsNetworkMapper3D::SetDefaultProperties(DataNode* node, BaseRenderer* renderer , bool overwrite) { // Initialize enumeration properties mitk::ConnectomicsRenderingSchemeProperty::Pointer connectomicsRenderingScheme = mitk::ConnectomicsRenderingSchemeProperty::New(); mitk::ConnectomicsRenderingEdgeFilteringProperty::Pointer connectomicsRenderingEdgeFiltering = mitk::ConnectomicsRenderingEdgeFilteringProperty::New(); mitk::ConnectomicsRenderingNodeFilteringProperty::Pointer connectomicsRenderingNodeFiltering = mitk::ConnectomicsRenderingNodeFilteringProperty::New(); mitk::ConnectomicsRenderingNodeColorParameterProperty::Pointer connectomicsRenderingNodeGradientColorParameter = mitk::ConnectomicsRenderingNodeColorParameterProperty::New(); mitk::ConnectomicsRenderingNodeRadiusParameterProperty::Pointer connectomicsRenderingNodeRadiusParameter = mitk::ConnectomicsRenderingNodeRadiusParameterProperty::New(); mitk::ConnectomicsRenderingEdgeColorParameterProperty::Pointer connectomicsRenderingEdgeGradientColorParameter = mitk::ConnectomicsRenderingEdgeColorParameterProperty::New(); mitk::ConnectomicsRenderingEdgeRadiusParameterProperty::Pointer connectomicsRenderingEdgeRadiusParameter = mitk::ConnectomicsRenderingEdgeRadiusParameterProperty::New(); mitk::ConnectomicsRenderingNodeThresholdParameterProperty::Pointer connectomicsRenderingNodeThresholdParameter = mitk::ConnectomicsRenderingNodeThresholdParameterProperty::New(); mitk::ConnectomicsRenderingEdgeThresholdParameterProperty::Pointer connectomicsRenderingEdgeThresholdParameter = mitk::ConnectomicsRenderingEdgeThresholdParameterProperty::New(); // set the properties node->AddProperty( connectomicsRenderingSchemePropertyName.c_str(), connectomicsRenderingScheme, renderer, overwrite ); node->AddProperty( connectomicsRenderingEdgeFilteringPropertyName.c_str(), connectomicsRenderingEdgeFiltering, renderer, overwrite ); node->AddProperty( connectomicsRenderingEdgeThresholdFilterParameterName.c_str(), connectomicsRenderingEdgeThresholdParameter, renderer, overwrite ); node->AddProperty( connectomicsRenderingEdgeThresholdFilterThresholdName.c_str(), connectomicsRenderingEdgeThresholdFilterThresholdDefault, renderer, overwrite ); node->AddProperty( connectomicsRenderingNodeFilteringPropertyName.c_str(), connectomicsRenderingNodeFiltering, renderer, overwrite ); node->AddProperty( connectomicsRenderingNodeThresholdFilterParameterName.c_str(), connectomicsRenderingNodeThresholdParameter, renderer, overwrite ); node->AddProperty( connectomicsRenderingNodeThresholdFilterThresholdName.c_str(), connectomicsRenderingNodeThresholdFilterThresholdDefault, renderer, overwrite ); node->AddProperty( connectomicsRenderingNodeGradientStartColorName.c_str(), connectomicsRenderingNodeGradientStartColorDefault, renderer, overwrite ); node->AddProperty( connectomicsRenderingNodeGradientEndColorName.c_str(), connectomicsRenderingNodeGradientEndColorDefault, renderer, overwrite ); node->AddProperty( connectomicsRenderingNodeGradientColorParameterName.c_str(), connectomicsRenderingNodeGradientColorParameter, renderer, overwrite ); node->AddProperty( connectomicsRenderingNodeRadiusStartName.c_str(), connectomicsRenderingNodeRadiusStartDefault, renderer, overwrite ); node->AddProperty( connectomicsRenderingNodeRadiusEndName.c_str(), connectomicsRenderingNodeRadiusEndDefault, renderer, overwrite ); node->AddProperty( connectomicsRenderingNodeRadiusParameterName.c_str(), connectomicsRenderingNodeRadiusParameter, renderer, overwrite ); node->AddProperty( connectomicsRenderingNodeChosenNodeName.c_str(), connectomicsRenderingNodeChosenNodeDefault, renderer, overwrite ); node->AddProperty( connectomicsRenderingEdgeGradientStartColorName.c_str(), connectomicsRenderingEdgeGradientStartColorDefault, renderer, overwrite ); node->AddProperty( connectomicsRenderingEdgeGradientEndColorName.c_str(), connectomicsRenderingEdgeGradientEndColorDefault, renderer, overwrite ); node->AddProperty( connectomicsRenderingEdgeGradientColorParameterName.c_str(), connectomicsRenderingEdgeGradientColorParameter, renderer, overwrite ); node->AddProperty( connectomicsRenderingEdgeRadiusStartName.c_str(), connectomicsRenderingEdgeRadiusStartDefault, renderer, overwrite ); node->AddProperty( connectomicsRenderingEdgeRadiusEndName.c_str(), connectomicsRenderingEdgeRadiusEndDefault, renderer, overwrite ); node->AddProperty( connectomicsRenderingEdgeRadiusParameterName.c_str(), connectomicsRenderingEdgeRadiusParameter, renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } void mitk::ConnectomicsNetworkMapper3D::ApplyProperties(mitk::BaseRenderer* renderer) { //TODO: implement } void mitk::ConnectomicsNetworkMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *mapper) { //TODO: implement } void mitk::ConnectomicsNetworkMapper3D::UpdateVtkObjects() { //TODO: implement } vtkProp* mitk::ConnectomicsNetworkMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { return m_NetworkAssembly; } bool mitk::ConnectomicsNetworkMapper3D::PropertiesChanged() { mitk::ConnectomicsRenderingSchemeProperty * renderingScheme = static_cast< mitk::ConnectomicsRenderingSchemeProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingSchemePropertyName.c_str() ) ); mitk::ConnectomicsRenderingEdgeFilteringProperty * edgeFilter = static_cast< mitk::ConnectomicsRenderingEdgeFilteringProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingEdgeFilteringPropertyName.c_str() ) ); mitk::FloatProperty * edgeThreshold = static_cast< mitk::FloatProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingEdgeThresholdFilterThresholdName.c_str() ) ); mitk::ConnectomicsRenderingNodeFilteringProperty * nodeFilter = static_cast< mitk::ConnectomicsRenderingNodeFilteringProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingNodeFilteringPropertyName.c_str() ) ); mitk::ConnectomicsRenderingNodeThresholdParameterProperty * nodeThresholdParameter = static_cast< mitk::ConnectomicsRenderingNodeThresholdParameterProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingNodeThresholdFilterParameterName.c_str() ) ); mitk::ConnectomicsRenderingEdgeThresholdParameterProperty * edgeThresholdParameter = static_cast< mitk::ConnectomicsRenderingEdgeThresholdParameterProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingEdgeThresholdFilterParameterName.c_str() ) ); mitk::FloatProperty * nodeThreshold = static_cast< mitk::FloatProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingNodeThresholdFilterThresholdName.c_str() ) ); mitk::ColorProperty * nodeColorStart = static_cast< mitk::ColorProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingNodeGradientStartColorName.c_str() ) ); mitk::ColorProperty * nodeColorEnd = static_cast< mitk::ColorProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingNodeGradientEndColorName.c_str() ) ); mitk::FloatProperty * nodeRadiusStart = static_cast< mitk::FloatProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingNodeRadiusStartName.c_str() ) ); mitk::FloatProperty * nodeRadiusEnd = static_cast< mitk::FloatProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingNodeRadiusEndName.c_str() ) ); mitk::StringProperty * chosenNode = static_cast< mitk::StringProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingNodeChosenNodeName.c_str() ) ); mitk::ColorProperty * edgeColorStart = static_cast< mitk::ColorProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingEdgeGradientStartColorName.c_str() ) ); mitk::ColorProperty * edgeColorEnd = static_cast< mitk::ColorProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingEdgeGradientEndColorName.c_str() ) ); mitk::FloatProperty * edgeRadiusStart = static_cast< mitk::FloatProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingEdgeRadiusStartName.c_str() ) ); mitk::FloatProperty * edgeRadiusEnd = static_cast< mitk::FloatProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingEdgeRadiusEndName.c_str() ) ); mitk::ConnectomicsRenderingNodeColorParameterProperty * nodeColorParameter = static_cast< mitk::ConnectomicsRenderingNodeColorParameterProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingNodeGradientColorParameterName.c_str() ) ); mitk::ConnectomicsRenderingNodeRadiusParameterProperty * nodeRadiusParameter = static_cast< mitk::ConnectomicsRenderingNodeRadiusParameterProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingNodeRadiusParameterName.c_str() ) ); mitk::ConnectomicsRenderingEdgeColorParameterProperty * edgeColorParameter = static_cast< mitk::ConnectomicsRenderingEdgeColorParameterProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingEdgeGradientColorParameterName.c_str() ) ); mitk::ConnectomicsRenderingEdgeRadiusParameterProperty * edgeRadiusParameter = static_cast< mitk::ConnectomicsRenderingEdgeRadiusParameterProperty * > ( this->GetDataNode()->GetProperty( connectomicsRenderingEdgeRadiusParameterName.c_str() ) ); if( m_ChosenRenderingScheme != renderingScheme->GetValueAsString() || m_ChosenEdgeFilter != edgeFilter->GetValueAsString() || m_EdgeThreshold != edgeThreshold->GetValue() || m_EdgeThresholdParameter != edgeThresholdParameter->GetValueAsString() || m_ChosenNodeFilter != nodeFilter->GetValueAsString() || m_NodeThreshold != nodeThreshold->GetValue() || m_NodeThresholdParameter != nodeThresholdParameter->GetValueAsString() || m_NodeColorStart != nodeColorStart->GetValue() || m_NodeColorEnd != nodeColorEnd->GetValue() || m_NodeRadiusStart != nodeRadiusStart->GetValue() || m_NodeRadiusEnd != nodeRadiusEnd->GetValue() || m_ChosenNodeLabel != chosenNode->GetValueAsString() || m_EdgeColorStart != edgeColorStart->GetValue() || m_EdgeColorEnd != edgeColorEnd->GetValue() || m_EdgeRadiusStart != edgeRadiusStart->GetValue() || m_EdgeRadiusEnd != edgeRadiusEnd->GetValue() || m_NodeColorParameter != nodeColorParameter->GetValueAsString() || m_NodeRadiusParameter != nodeRadiusParameter->GetValueAsString() || m_EdgeColorParameter != edgeColorParameter->GetValueAsString() || m_EdgeRadiusParameter != edgeRadiusParameter->GetValueAsString() ) { m_ChosenRenderingScheme = renderingScheme->GetValueAsString(); m_ChosenEdgeFilter = edgeFilter->GetValueAsString(); m_EdgeThreshold = edgeThreshold->GetValue(); m_EdgeThresholdParameter = edgeThresholdParameter->GetValueAsString(); m_ChosenNodeFilter = nodeFilter->GetValueAsString(); m_NodeThreshold = nodeThreshold->GetValue(); m_NodeThresholdParameter = nodeThresholdParameter->GetValueAsString(); m_NodeColorStart = nodeColorStart->GetValue(); m_NodeColorEnd = nodeColorEnd->GetValue(); m_NodeRadiusStart = nodeRadiusStart->GetValue(); m_NodeRadiusEnd = nodeRadiusEnd->GetValue(); m_ChosenNodeLabel = chosenNode->GetValueAsString(); m_EdgeColorStart = edgeColorStart->GetValue(); m_EdgeColorEnd = edgeColorEnd->GetValue(); m_EdgeRadiusStart = edgeRadiusStart->GetValue(); m_EdgeRadiusEnd = edgeRadiusEnd->GetValue(); m_NodeColorParameter = nodeColorParameter->GetValueAsString(); m_NodeRadiusParameter = nodeRadiusParameter->GetValueAsString(); m_EdgeColorParameter = edgeColorParameter->GetValueAsString(); m_EdgeRadiusParameter = edgeRadiusParameter->GetValueAsString(); return true; } return false; } double mitk::ConnectomicsNetworkMapper3D::FillNodeParameterVector( std::vector< double > * parameterVector, std::string parameterName ) { int end( parameterVector->size() ); // constant parameter - uniform style if( parameterName == connectomicsRenderingNodeParameterConstant ) { for(int index(0); index < end; index++) { parameterVector->at( index ) = 1.0; } return 1.0; } double maximum( 0.0 ); // using the degree as parameter if( parameterName == connectomicsRenderingNodeParameterDegree ) { std::vector< int > vectorOfDegree = this->GetInput()->GetDegreeOfNodes(); for(int index(0); index < end; index++) { parameterVector->at( index ) = vectorOfDegree[ index ]; } maximum = *std::max_element( parameterVector->begin(), parameterVector->end() ); } // using betweenness centrality as parameter if( parameterName == connectomicsRenderingNodeParameterBetweenness ) { std::vector< double > vectorOfBetweenness = this->GetInput()->GetNodeBetweennessVector(); for(int index(0); index < end; index++) { parameterVector->at( index ) = vectorOfBetweenness[index]; } maximum = *std::max_element( parameterVector->begin(), parameterVector->end() ); } // using clustering coefficient as parameter if( parameterName == connectomicsRenderingNodeParameterClustering ) { const std::vector< double > vectorOfClustering = this->GetInput()->GetLocalClusteringCoefficients(); for(int index(0); index < end; index++) { parameterVector->at( index ) = vectorOfClustering[index]; } maximum = *std::max_element( parameterVector->begin(), parameterVector->end() ); } // using distance to a specific node as parameter if( parameterName == connectomicsRenderingNodeParameterColoringShortestPath ) { bool labelFound( this->GetInput()->CheckForLabel( m_ChosenNodeLabel ) ); // check whether the chosen node is valid if( !labelFound ) { MITK_WARN << "Node chosen for rendering is not valid."; for(int index(0); index < end; index++) { parameterVector->at( index ) = 1.0; } return 1.0; } else { const std::vector< double > distanceVector = this->GetInput()->GetShortestDistanceVectorFromLabel( m_ChosenNodeLabel ); for(int index(0); index < end; index++) { parameterVector->at( index ) = distanceVector[index]; } maximum = *std::max_element( parameterVector->begin(), parameterVector->end() ); } } // if the maximum is nearly zero if( std::abs( maximum ) < mitk::eps ) { maximum = 1.0; } return maximum; } double mitk::ConnectomicsNetworkMapper3D::FillEdgeParameterVector( std::vector< double > * parameterVector, std::string parameterName ) { int end( parameterVector->size() ); // constant parameter - uniform style if( parameterName == connectomicsRenderingEdgeParameterConstant ) { for(int index(0); index < end; index++) { parameterVector->at( index ) = 1.0; } return 1.0; } double maximum( 0.0 ); // using the weight as parameter if( parameterName == connectomicsRenderingEdgeParameterWeight ) { std::vector< std::pair< std::pair< mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode > , mitk::ConnectomicsNetwork::NetworkEdge > > vectorOfEdges = this->GetInput()->GetVectorOfAllEdges(); for(int index(0); index < end; index++) { parameterVector->at( index ) = vectorOfEdges[ index ].second.weight; } maximum = *std::max_element( parameterVector->begin(), parameterVector->end() ); } // using the edge centrality as parameter if( parameterName == connectomicsRenderingEdgeParameterCentrality ) { const std::vector< double > vectorOfCentrality = this->GetInput()->GetEdgeBetweennessVector(); for(int index(0); index < end; index++) { parameterVector->at( index ) = vectorOfCentrality[index]; } maximum = *std::max_element( parameterVector->begin(), parameterVector->end() ); } // if the maximum is nearly zero if( std::abs( maximum ) < mitk::eps ) { maximum = 1.0; } return maximum; } void mitk::ConnectomicsNetworkMapper3D::FillNodeFilterBoolVector( std::vector< bool > * boolVector, std::string parameterName ) { std::vector< double > parameterVector; parameterVector.resize( boolVector->size() ); int end( parameterVector.size() ); // using the degree as parameter if( parameterName == connectomicsRenderingNodeParameterDegree ) { std::vector< int > vectorOfDegree = this->GetInput()->GetDegreeOfNodes(); for(int index(0); index < end; index++) { parameterVector.at( index ) = vectorOfDegree[ index ]; } } // using betweenness centrality as parameter if( parameterName == connectomicsRenderingNodeParameterBetweenness ) { std::vector< double > vectorOfBetweenness = this->GetInput()->GetNodeBetweennessVector(); for(int index(0); index < end; index++) { parameterVector.at( index ) = vectorOfBetweenness[index]; } } // using clustering coefficient as parameter if( parameterName == connectomicsRenderingNodeParameterClustering ) { const std::vector< double > vectorOfClustering = this->GetInput()->GetLocalClusteringCoefficients(); for(int index(0); index < end; index++) { parameterVector.at( index ) = vectorOfClustering[index]; } } for( int index( 0 ), end( boolVector->size() ); index < end; index++ ) { if( parameterVector.at( index ) >= m_NodeThreshold ) { boolVector->at( index ) = true; } else { boolVector->at( index ) = false; } } return; } void mitk::ConnectomicsNetworkMapper3D::FillEdgeFilterBoolVector( std::vector< bool > * boolVector, std::string parameterName ) { std::vector< double > parameterVector; parameterVector.resize( boolVector->size() ); int end( parameterVector.size() ); // using the weight as parameter if( parameterName == connectomicsRenderingEdgeParameterWeight ) { std::vector< std::pair< std::pair< mitk::ConnectomicsNetwork::NetworkNode, mitk::ConnectomicsNetwork::NetworkNode > , mitk::ConnectomicsNetwork::NetworkEdge > > vectorOfEdges = this->GetInput()->GetVectorOfAllEdges(); for(int index(0); index < end; index++) { parameterVector.at( index ) = vectorOfEdges[ index ].second.weight; } } // using the edge centrality as parameter if( parameterName == connectomicsRenderingEdgeParameterCentrality ) { const std::vector< double > vectorOfCentrality = this->GetInput()->GetEdgeBetweennessVector(); for(int index(0); index < end; index++) { parameterVector.at( index ) = vectorOfCentrality[index]; } } for( int index( 0 ), end( boolVector->size() ); index < end; index++ ) { if( parameterVector.at( index ) >= m_EdgeThreshold ) { boolVector->at( index ) = true; } else { boolVector->at( index ) = false; } } return; } diff --git a/Modules/DiffusionImaging/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.h b/Modules/DiffusionImaging/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.h index b596449f0f..391c32906d 100644 --- a/Modules/DiffusionImaging/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.h +++ b/Modules/DiffusionImaging/Connectomics/Rendering/mitkConnectomicsNetworkMapper3D.h @@ -1,136 +1,135 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef ConnectomicsNetworkMapper3D_H_HEADER_INCLUDED #define ConnectomicsNetworkMapper3D_H_HEADER_INCLUDED // VTK includes #include #include "vtkPropAssembly.h" // MITK includes // base class -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" // data type #include "mitkConnectomicsNetwork.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ConnectomicsExports.h" namespace mitk { /** * \brief Mapper for Networks * \ingroup Mapper */ - class Connectomics_EXPORT ConnectomicsNetworkMapper3D : public VtkMapper3D + class Connectomics_EXPORT ConnectomicsNetworkMapper3D : public VtkMapper { public: - mitkClassMacro(ConnectomicsNetworkMapper3D, VtkMapper3D); + mitkClassMacro(ConnectomicsNetworkMapper3D, VtkMapper); itkNewMacro(Self); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); //looks like deprecated.. should be replaced bz GetViewProp() static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); virtual void ApplyProperties(mitk::BaseRenderer* renderer); static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); - virtual void GenerateData(); virtual const mitk::ConnectomicsNetwork* GetInput(); protected: ConnectomicsNetworkMapper3D(); virtual ~ConnectomicsNetworkMapper3D(); void UpdateVtkObjects(); vtkPropAssembly *m_NetworkAssembly; /** * \brief Returns true if the properties have changed since the last data generation */ bool PropertiesChanged(); // Create vectors for customizing color and radius and return maximum double FillNodeParameterVector( std::vector< double > * parameterVector, std::string parameterName ); double FillEdgeParameterVector( std::vector< double > * parameterVector, std::string parameterName ); void FillNodeFilterBoolVector( std::vector< bool > * boolVector, std::string parameterName ); void FillEdgeFilterBoolVector( std::vector< bool > * boolVector, std::string parameterName ); // Property storing members std::string m_ChosenRenderingScheme; std::string m_ChosenEdgeFilter; std::string m_EdgeThresholdParameter; double m_EdgeThreshold; std::string m_ChosenNodeFilter; std::string m_NodeThresholdParameter; double m_NodeThreshold; mitk::Color m_NodeColorStart; mitk::Color m_NodeColorEnd; double m_NodeRadiusStart; double m_NodeRadiusEnd; std::string m_ChosenNodeLabel; mitk::Color m_EdgeColorStart; mitk::Color m_EdgeColorEnd; double m_EdgeRadiusStart; double m_EdgeRadiusEnd; std::string m_NodeRadiusParameter; std::string m_NodeColorParameter; std::string m_EdgeRadiusParameter; std::string m_EdgeColorParameter; }; } // namespace mitk #endif /* ConnectomicsNetworkMapper3D_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkCompositeMapper.h b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkCompositeMapper.h index acd8ef65be..b587249019 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkCompositeMapper.h +++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkCompositeMapper.h @@ -1,170 +1,159 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef COMPOSITEMAPPER_H_HEADER_INCLUDED #define COMPOSITEMAPPER_H_HEADER_INCLUDED -#include "mitkGLMapper2D.h" -#include "mitkVtkMapper2D.h" +#include "mitkGLMapper.h" +#include "mitkVtkMapper.h" #include "mitkQBallImage.h" #include "mitkImageVtkMapper2D.h" #include "mitkOdfVtkMapper2D.h" #include "mitkLevelWindowProperty.h" namespace mitk { class CopyImageMapper2D : public ImageVtkMapper2D { public: mitkClassMacro(CopyImageMapper2D,ImageVtkMapper2D); itkNewMacro(Self); friend class CompositeMapper; }; //##Documentation //## @brief Composite pattern for combination of different mappers //## @ingroup Mapper - class CompositeMapper : public VtkMapper2D + class CompositeMapper : public VtkMapper { public: - mitkClassMacro(CompositeMapper,VtkMapper2D) - itkNewMacro(Self) + mitkClassMacro(CompositeMapper,VtkMapper); + itkNewMacro(Self); virtual void MitkRenderOverlay(BaseRenderer* renderer) { m_ImgMapper->MitkRenderOverlay(renderer); m_OdfMapper->MitkRenderOverlay(renderer); } virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer) { m_ImgMapper->MitkRenderOpaqueGeometry(renderer); m_OdfMapper->MitkRenderOpaqueGeometry(renderer); if( mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ) == 0 ) { renderer->Modified(); } } virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer) { m_ImgMapper->MitkRenderTranslucentGeometry(renderer); m_OdfMapper->MitkRenderTranslucentGeometry(renderer); } virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer) { m_ImgMapper->MitkRenderVolumetricGeometry(renderer); m_OdfMapper->MitkRenderVolumetricGeometry(renderer); } void SetDataNode(DataNode* node) { m_DataNode = node; m_ImgMapper->SetDataNode(node); m_OdfMapper->SetDataNode(node); } mitk::ImageVtkMapper2D::Pointer GetImageMapper() { ImageVtkMapper2D* retval = m_ImgMapper; return retval; } - bool IsVtkBased() const - { - return m_OdfMapper->IsVtkBased(); - } - bool HasVtkProp( const vtkProp* prop, BaseRenderer* renderer ) { return m_OdfMapper->HasVtkProp(prop, renderer); } void ReleaseGraphicsResources(vtkWindow* window) { m_ImgMapper->ReleaseGraphicsResources(window); m_OdfMapper->ReleaseGraphicsResources(window); } static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ) { mitk::OdfVtkMapper2D::SetDefaultProperties(node, renderer, overwrite); mitk::CopyImageMapper2D::SetDefaultProperties(node, renderer, overwrite); mitk::LevelWindow opaclevwin; opaclevwin.SetRangeMinMax(0,255); opaclevwin.SetWindowBounds(0,0); mitk::LevelWindowProperty::Pointer prop = mitk::LevelWindowProperty::New(opaclevwin); node->AddProperty( "opaclevelwindow", prop ); } bool IsLODEnabled( BaseRenderer * renderer ) const { return m_ImgMapper->IsLODEnabled(renderer) || m_OdfMapper->IsLODEnabled(renderer); } vtkProp* GetVtkProp(mitk::BaseRenderer* renderer) { vtkPropAssembly* assembly = vtkPropAssembly::New(); assembly->AddPart( m_OdfMapper->GetVtkProp(renderer)); assembly->AddPart( m_ImgMapper->GetVtkProp(renderer)); return assembly; } - void SetGeometry3D(const mitk::Geometry3D* aGeometry3D) - { - m_ImgMapper->SetGeometry3D(aGeometry3D); - m_OdfMapper->SetGeometry3D(aGeometry3D); - } + protected: virtual void Update(mitk::BaseRenderer* renderer) { m_OdfMapper->Update(renderer); GenerateDataForRenderer(renderer); } - protected: - virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer) { m_ImgMapper->GenerateDataForRenderer(renderer); // if( mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ) > 0 ) // { // m_OdfMapper->GenerateDataForRenderer(renderer); // } } CompositeMapper(); virtual ~CompositeMapper(); private: mitk::OdfVtkMapper2D::Pointer m_OdfMapper; mitk::CopyImageMapper2D::Pointer m_ImgMapper; }; } // namespace mitk #endif /* COMPOSITEMAPPER_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h index 307b5ab403..ebb39a1a04 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h +++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.h @@ -1,145 +1,145 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef ODFVTKMAPPER2D_H_HEADER_INCLUDED #define ODFVTKMAPPER2D_H_HEADER_INCLUDED -#include "mitkVtkMapper2D.h" +#include "mitkVtkMapper.h" #include "vtkPropAssembly.h" #include "vtkAppendPolyData.h" #include "vtkActor.h" #include "vtkPolyDataMapper.h" #include "vtkPlane.h" #include "vtkCutter.h" #include "vtkClipPolyData.h" #include "vtkTransform.h" #include "vtkDataArrayTemplate.h" #include "vtkSmartPointer.h" #include "vtkOdfSource.h" #include "vtkThickPlane.h" namespace mitk { //##Documentation //## @brief Mapper for spherical object densitiy function representations //## template -class OdfVtkMapper2D : public VtkMapper2D +class OdfVtkMapper2D : public VtkMapper { struct OdfDisplayGeometry { vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; Vector3D normal; double d, d1, d2; mitk::Point3D M3D, L3D, O3D; vtkFloatingPointType vp_original[ 3 ], vnormal_original[ 3 ]; mitk::Vector2D size, origin; bool Equals(OdfDisplayGeometry other) { return other.vp_original[0] == vp[0] && other.vp_original[1] == vp[1] && other.vp_original[2] == vp[2] && other.vnormal_original[0] == vnormal[0] && other.vnormal_original[1] == vnormal[1] && other.vnormal_original[2] == vnormal[2] && other.size[0] == size[0] && other.size[1] == size[1] && other.origin[0] == origin[0] && other.origin[1] == origin[1]; } }; public: - mitkClassMacro(OdfVtkMapper2D,VtkMapper2D) + mitkClassMacro(OdfVtkMapper2D,VtkMapper) itkNewMacro(Self) virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); bool IsVisibleOdfs(mitk::BaseRenderer* renderer); virtual void MitkRenderOverlay(mitk::BaseRenderer* renderer); virtual void MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer); virtual void MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer); virtual void MitkRenderVolumetricGeometry(mitk::BaseRenderer* /*renderer*/){} OdfDisplayGeometry MeasureDisplayedGeometry(mitk::BaseRenderer* renderer); double GetMinImageSpacing( int index ); void ApplyPropertySettings(); virtual void Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry dispGeo); virtual int GetIndex(mitk::BaseRenderer* renderer); static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false); virtual void Update(mitk::BaseRenderer * renderer); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); virtual bool IsLODEnabled( BaseRenderer * /*renderer*/ ) const { return true; } class LocalStorage : public mitk::Mapper::BaseLocalStorage { public: std::vector< vtkSmartPointer > m_PropAssemblies; std::vector< vtkSmartPointer > m_OdfsPlanes; std::vector< vtkSmartPointer > m_OdfsActors; std::vector< vtkSmartPointer > m_OdfsMappers; vtkSmartPointer< vtkPolyData > m_TemplateOdf; itk::TimeStamp m_LastUpdateTime; /** \brief Default constructor of the local storage. */ LocalStorage(); /** \brief Default deconstructor of the local storage. */ ~LocalStorage() { } }; protected: OdfVtkMapper2D(); virtual ~OdfVtkMapper2D(); static void GlyphMethod(void *arg); bool IsPlaneRotated(mitk::BaseRenderer* renderer); private: mitk::Image* GetInput(); static vtkSmartPointer m_OdfTransform; static vtkSmartPointer m_OdfSource; static float m_Scaling; static int m_Normalization; static int m_ScaleBy; static float m_IndexParam1; static float m_IndexParam2; int m_ShowMaxNumber; std::vector< vtkSmartPointer > m_Planes; std::vector< vtkSmartPointer > m_Cutters; std::vector< vtkSmartPointer > m_ThickPlanes1; std::vector< vtkSmartPointer > m_Clippers1; std::vector< vtkSmartPointer > m_ThickPlanes2; std::vector< vtkSmartPointer > m_Clippers2; vtkImageData* m_VtkImage ; OdfDisplayGeometry m_LastDisplayGeometry; mitk::Mapper::LocalStorageHandler m_LSH; }; } // namespace mitk #include "mitkOdfVtkMapper2D.txx" #endif /* ODFVTKMAPPER2D_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx index 5e5884a2bd..444ca013a9 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx +++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkOdfVtkMapper2D.txx @@ -1,882 +1,884 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkOdfVtkMapper2D_txx__ #define __mitkOdfVtkMapper2D_txx__ #include "mitkOdfVtkMapper2D.h" #include "mitkDataNode.h" #include "mitkBaseRenderer.h" #include "mitkMatrixConvert.h" #include "mitkGeometry3D.h" #include "mitkOdfNormalizationMethodProperty.h" #include "mitkOdfScaleByProperty.h" #include "mitkProperties.h" #include "mitkTensorImage.h" #include "vtkSphereSource.h" #include "vtkPropCollection.h" #include "vtkMaskedGlyph3D.h" #include "vtkGlyph2D.h" #include "vtkGlyph3D.h" #include "vtkMaskedProgrammableGlyphFilter.h" #include "vtkImageData.h" #include "vtkLinearTransform.h" #include "vtkCamera.h" #include "vtkPointData.h" #include "vtkTransformPolyDataFilter.h" #include "vtkTransform.h" #include "vtkOdfSource.h" #include "vtkDoubleArray.h" #include "vtkLookupTable.h" #include "vtkProperty.h" #include "vtkPolyDataNormals.h" #include "vtkLight.h" #include "vtkLightCollection.h" #include "vtkMath.h" #include "vtkFloatArray.h" #include "vtkDelaunay2D.h" #include "vtkMapper.h" #include "vtkRenderer.h" #include "itkOrientationDistributionFunction.h" #include "itkFixedArray.h" #include #include "vtkOpenGLRenderer.h" #define _USE_MATH_DEFINES #include template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfTransform = vtkSmartPointer::New(); template vtkSmartPointer mitk::OdfVtkMapper2D::m_OdfSource = vtkSmartPointer::New(); template float mitk::OdfVtkMapper2D::m_Scaling; template int mitk::OdfVtkMapper2D::m_Normalization; template int mitk::OdfVtkMapper2D::m_ScaleBy; template float mitk::OdfVtkMapper2D::m_IndexParam1; template float mitk::OdfVtkMapper2D::m_IndexParam2; #define ODF_MAPPER_PI M_PI template mitk::OdfVtkMapper2D::LocalStorage::LocalStorage() { m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_PropAssemblies.push_back(vtkPropAssembly::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes.push_back(vtkAppendPolyData::New()); m_OdfsPlanes[0]->AddInput(vtkPolyData::New()); m_OdfsPlanes[1]->AddInput(vtkPolyData::New()); m_OdfsPlanes[2]->AddInput(vtkPolyData::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors.push_back(vtkActor::New()); m_OdfsActors[0]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[1]->GetProperty()->SetInterpolationToGouraud(); m_OdfsActors[2]->GetProperty()->SetInterpolationToGouraud(); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); m_OdfsMappers.push_back(vtkPolyDataMapper::New()); vtkLookupTable *lut = vtkLookupTable::New(); m_OdfsMappers[0]->SetLookupTable(lut); m_OdfsMappers[1]->SetLookupTable(lut); m_OdfsMappers[2]->SetLookupTable(lut); m_OdfsActors[0]->SetMapper(m_OdfsMappers[0]); m_OdfsActors[1]->SetMapper(m_OdfsMappers[1]); m_OdfsActors[2]->SetMapper(m_OdfsMappers[2]); } template mitk::OdfVtkMapper2D ::OdfVtkMapper2D() { m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Planes.push_back(vtkPlane::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters.push_back(vtkCutter::New()); m_Cutters[0]->SetCutFunction( m_Planes[0] ); m_Cutters[0]->GenerateValues( 1, 0, 1 ); m_Cutters[1]->SetCutFunction( m_Planes[1] ); m_Cutters[1]->GenerateValues( 1, 0, 1 ); m_Cutters[2]->SetCutFunction( m_Planes[2] ); m_Cutters[2]->GenerateValues( 1, 0, 1 ); // Windowing the cutted planes in direction 1 m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_ThickPlanes1.push_back(vtkThickPlane::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1.push_back(vtkClipPolyData::New()); m_Clippers1[0]->SetClipFunction( m_ThickPlanes1[0] ); m_Clippers1[1]->SetClipFunction( m_ThickPlanes1[1] ); m_Clippers1[2]->SetClipFunction( m_ThickPlanes1[2] ); // Windowing the cutted planes in direction 2 m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_ThickPlanes2.push_back(vtkThickPlane::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2.push_back(vtkClipPolyData::New()); m_Clippers2[0]->SetClipFunction( m_ThickPlanes2[0] ); m_Clippers2[1]->SetClipFunction( m_ThickPlanes2[1] ); m_Clippers2[2]->SetClipFunction( m_ThickPlanes2[2] ); m_ShowMaxNumber = 500; } template mitk::OdfVtkMapper2D ::~OdfVtkMapper2D() { } template mitk::Image* mitk::OdfVtkMapper2D ::GetInput() { return static_cast ( m_DataNode->GetData() ); } template vtkProp* mitk::OdfVtkMapper2D ::GetVtkProp(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); return localStorage->m_PropAssemblies[GetIndex(renderer)]; } template int mitk::OdfVtkMapper2D ::GetIndex(mitk::BaseRenderer* renderer) { if(!strcmp(renderer->GetName(),"stdmulti.widget1")) return 0; if(!strcmp(renderer->GetName(),"stdmulti.widget2")) return 1; if(!strcmp(renderer->GetName(),"stdmulti.widget3")) return 2; return 0; } template void mitk::OdfVtkMapper2D ::GlyphMethod(void *arg) { vtkMaskedProgrammableGlyphFilter* pfilter=(vtkMaskedProgrammableGlyphFilter*)arg; double point[3]; double debugpoint[3]; pfilter->GetPoint(point); pfilter->GetPoint(debugpoint); itk::Point p(point); Vector3D spacing = pfilter->GetGeometry()->GetSpacing(); p[0] /= spacing[0]; p[1] /= spacing[1]; p[2] /= spacing[2]; mitk::Point3D p2; pfilter->GetGeometry()->IndexToWorld( p, p2 ); point[0] = p2[0]; point[1] = p2[1]; point[2] = p2[2]; vtkPointData* data = pfilter->GetPointData(); vtkDataArray* odfvals = data->GetArray("vector"); vtkIdType id = pfilter->GetPointId(); m_OdfTransform->Identity(); m_OdfTransform->Translate(point[0],point[1],point[2]); typedef itk::OrientationDistributionFunction OdfType; OdfType odf; if(odfvals->GetNumberOfComponents()==6) { float tensorelems[6] = { (float)odfvals->GetComponent(id,0), (float)odfvals->GetComponent(id,1), (float)odfvals->GetComponent(id,2), (float)odfvals->GetComponent(id,3), (float)odfvals->GetComponent(id,4), (float)odfvals->GetComponent(id,5), }; itk::DiffusionTensor3D tensor(tensorelems); odf.InitFromTensor(tensor); } else { for(int i=0; iGetComponent(id,i); } switch(m_ScaleBy) { case ODFSB_NONE: m_OdfSource->SetScale(m_Scaling); break; case ODFSB_GFA: m_OdfSource->SetScale(m_Scaling*odf.GetGeneralizedGFA(m_IndexParam1, m_IndexParam2)); break; case ODFSB_PC: m_OdfSource->SetScale(m_Scaling*odf.GetPrincipleCurvature(m_IndexParam1, m_IndexParam2, 0)); break; } m_OdfSource->SetNormalization(m_Normalization); m_OdfSource->SetOdf(odf); m_OdfSource->Modified(); } template typename mitk::OdfVtkMapper2D::OdfDisplayGeometry mitk::OdfVtkMapper2D ::MeasureDisplayedGeometry(mitk::BaseRenderer* renderer) { Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); // set up the cutter orientation according to the current geometry of // the renderers plane vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; Point3D point = worldPlaneGeometry->GetOrigin(); Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( point.Get_vnl_vector(), vp ); vnl2vtk( normal.Get_vnl_vector(), vnormal ); mitk::DisplayGeometry::Pointer dispGeometry = renderer->GetDisplayGeometry(); mitk::Vector2D size = dispGeometry->GetSizeInMM(); mitk::Vector2D origin = dispGeometry->GetOriginInMM(); // // |------O------| // | d2 | // L d1 M | // | | // |-------------| // mitk::Vector2D M; mitk::Vector2D L; mitk::Vector2D O; M[0] = origin[0] + size[0]/2; M[1] = origin[1] + size[1]/2; L[0] = origin[0]; L[1] = origin[1] + size[1]/2; O[0] = origin[0] + size[0]/2; O[1] = origin[1] + size[1]; mitk::Point2D point1; point1[0] = M[0]; point1[1] = M[1]; mitk::Point3D M3D; dispGeometry->Map(point1, M3D); point1[0] = L[0]; point1[1] = L[1]; mitk::Point3D L3D; dispGeometry->Map(point1, L3D); point1[0] = O[0]; point1[1] = O[1]; mitk::Point3D O3D; dispGeometry->Map(point1, O3D); double d1 = sqrt((M3D[0]-L3D[0])*(M3D[0]-L3D[0]) + (M3D[1]-L3D[1])*(M3D[1]-L3D[1]) + (M3D[2]-L3D[2])*(M3D[2]-L3D[2])); double d2 = sqrt((M3D[0]-O3D[0])*(M3D[0]-O3D[0]) + (M3D[1]-O3D[1])*(M3D[1]-O3D[1]) + (M3D[2]-O3D[2])*(M3D[2]-O3D[2])); double d = d1>d2 ? d1 : d2; d = d2; OdfDisplayGeometry retval; retval.vp[0] = vp[0]; retval.vp[1] = vp[1]; retval.vp[2] = vp[2]; retval.vnormal[0] = vnormal[0]; retval.vnormal[1] = vnormal[1]; retval.vnormal[2] = vnormal[2]; retval.normal[0] = normal[0]; retval.normal[1] = normal[1]; retval.normal[2] = normal[2]; retval.d = d; retval.d1 = d1; retval.d2 = d2; retval.M3D[0] = M3D[0]; retval.M3D[1] = M3D[1]; retval.M3D[2] = M3D[2]; retval.L3D[0] = L3D[0]; retval.L3D[1] = L3D[1]; retval.L3D[2] = L3D[2]; retval.O3D[0] = O3D[0]; retval.O3D[1] = O3D[1]; retval.O3D[2] = O3D[2]; retval.vp_original[0] = vp[0]; retval.vp_original[1] = vp[1]; retval.vp_original[2] = vp[2]; retval.vnormal_original[0] = vnormal[0]; retval.vnormal_original[1] = vnormal[1]; retval.vnormal_original[2] = vnormal[2]; retval.size[0] = size[0]; retval.size[1] = size[1]; retval.origin[0] = origin[0]; retval.origin[1] = origin[1]; return retval; } template void mitk::OdfVtkMapper2D ::Slice(mitk::BaseRenderer* renderer, OdfDisplayGeometry dispGeo) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); int index = GetIndex(renderer); vtkSmartPointer inversetransform = vtkSmartPointer::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); // vtk works in axis align coords // thus the normal also must be axis align, since // we do not allow arbitrary cutting through volume // // vnormal should already be axis align, but in order // to get rid of precision effects, we set the two smaller // components to zero here int dims[3]; m_VtkImage->GetDimensions(dims); double spac[3]; m_VtkImage->GetSpacing(spac); if(fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[1]) && fabs(dispGeo.vnormal[0]) > fabs(dispGeo.vnormal[2]) ) { if(fabs(dispGeo.vp[0]/spac[0]) < 0.4) dispGeo.vp[0] = 0.4*spac[0]; if(fabs(dispGeo.vp[0]/spac[0]) > (dims[0]-1)-0.4) dispGeo.vp[0] = ((dims[0]-1)-0.4)*spac[0]; dispGeo.vnormal[1] = 0; dispGeo.vnormal[2] = 0; } if(fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[0]) && fabs(dispGeo.vnormal[1]) > fabs(dispGeo.vnormal[2]) ) { if(fabs(dispGeo.vp[1]/spac[1]) < 0.4) dispGeo.vp[1] = 0.4*spac[1]; if(fabs(dispGeo.vp[1]/spac[1]) > (dims[1]-1)-0.4) dispGeo.vp[1] = ((dims[1]-1)-0.4)*spac[1]; dispGeo.vnormal[0] = 0; dispGeo.vnormal[2] = 0; } if(fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[1]) && fabs(dispGeo.vnormal[2]) > fabs(dispGeo.vnormal[0]) ) { if(fabs(dispGeo.vp[2]/spac[2]) < 0.4) dispGeo.vp[2] = 0.4*spac[2]; if(fabs(dispGeo.vp[2]/spac[2]) > (dims[2]-1)-0.4) dispGeo.vp[2] = ((dims[2]-1)-0.4)*spac[2]; dispGeo.vnormal[0] = 0; dispGeo.vnormal[1] = 0; } m_Planes[index]->SetTransform( (vtkAbstractTransform*)NULL ); m_Planes[index]->SetOrigin( dispGeo.vp ); m_Planes[index]->SetNormal( dispGeo.vnormal ); vtkSmartPointer points; vtkSmartPointer tmppoints; vtkSmartPointer polydata; vtkSmartPointer pointdata; vtkSmartPointer delaunay; vtkSmartPointer cuttedPlane; // the cutter only works if we do not have a 2D-image // or if we have a 2D-image and want to see the whole image. // // for side views of 2D-images, we need some special treatment if(!( (dims[0] == 1 && dispGeo.vnormal[0] != 0) || (dims[1] == 1 && dispGeo.vnormal[1] != 0) || (dims[2] == 1 && dispGeo.vnormal[2] != 0) )) { m_Cutters[index]->SetCutFunction( m_Planes[index] ); m_Cutters[index]->SetInput( m_VtkImage ); m_Cutters[index]->Update(); cuttedPlane = m_Cutters[index]->GetOutput(); } else { // cutting of a 2D-Volume does not work, // so we have to build up our own polydata object cuttedPlane = vtkPolyData::New(); points = vtkPoints::New(); points->SetNumberOfPoints(m_VtkImage->GetNumberOfPoints()); for(int i=0; iGetNumberOfPoints(); i++) { points->SetPoint(i, m_VtkImage->GetPoint(i)); } cuttedPlane->SetPoints(points); pointdata = vtkFloatArray::New(); int comps = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfComponents(); pointdata->SetNumberOfComponents(comps); int tuples = m_VtkImage->GetPointData()->GetScalars()->GetNumberOfTuples(); pointdata->SetNumberOfTuples(tuples); for(int i=0; iSetTuple(i,m_VtkImage->GetPointData()->GetScalars()->GetTuple(i)); pointdata->SetName( "vector" ); cuttedPlane->GetPointData()->AddArray(pointdata); int nZero1, nZero2; if(dims[0]==1) { nZero1 = 1; nZero2 = 2; } else if(dims[1]==1) { nZero1 = 0; nZero2 = 2; } else { nZero1 = 0; nZero2 = 1; } tmppoints = vtkPoints::New(); for(int j=0; jGetNumberOfPoints(); j++){ double pt[3]; m_VtkImage->GetPoint(j,pt); tmppoints->InsertNextPoint(pt[nZero1],pt[nZero2],0); } polydata = vtkPolyData::New(); polydata->SetPoints( tmppoints ); delaunay = vtkDelaunay2D::New(); delaunay->SetInput( polydata ); delaunay->Update(); vtkCellArray* polys = delaunay->GetOutput()->GetPolys(); cuttedPlane->SetPolys(polys); } if(cuttedPlane->GetNumberOfPoints()) { // WINDOWING HERE inversetransform = vtkTransform::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; ((vtkTransform*)vtktransform)->GetScale(myscale); inversetransform->PostMultiply(); inversetransform->Scale(1*myscale[0],1*myscale[1],1*myscale[2]); dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.O3D[0]; dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.O3D[1]; dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.O3D[2]; vtkMath::Normalize(dispGeo.vnormal); dispGeo.vp[0] = dispGeo.M3D[0]; dispGeo.vp[1] = dispGeo.M3D[1]; dispGeo.vp[2] = dispGeo.M3D[2]; inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); m_ThickPlanes1[index]->count = 0; m_ThickPlanes1[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes1[index]->SetPose( dispGeo.vnormal, dispGeo.vp ); m_ThickPlanes1[index]->SetThickness(dispGeo.d2); m_Clippers1[index]->SetClipFunction( m_ThickPlanes1[index] ); m_Clippers1[index]->SetInput( cuttedPlane ); m_Clippers1[index]->SetInsideOut(1); m_Clippers1[index]->Update(); dispGeo.vnormal[0] = dispGeo.M3D[0]-dispGeo.L3D[0]; dispGeo.vnormal[1] = dispGeo.M3D[1]-dispGeo.L3D[1]; dispGeo.vnormal[2] = dispGeo.M3D[2]-dispGeo.L3D[2]; vtkMath::Normalize(dispGeo.vnormal); dispGeo.vp[0] = dispGeo.M3D[0]; dispGeo.vp[1] = dispGeo.M3D[1]; dispGeo.vp[2] = dispGeo.M3D[2]; inversetransform->TransformPoint( dispGeo.vp, dispGeo.vp ); inversetransform->TransformNormalAtPoint( dispGeo.vp, dispGeo.vnormal, dispGeo.vnormal ); m_ThickPlanes2[index]->count = 0; m_ThickPlanes2[index]->SetTransform((vtkAbstractTransform*)NULL ); m_ThickPlanes2[index]->SetPose( dispGeo.vnormal, dispGeo.vp ); m_ThickPlanes2[index]->SetThickness(dispGeo.d1); m_Clippers2[index]->SetClipFunction( m_ThickPlanes2[index] ); m_Clippers2[index]->SetInput( m_Clippers1[index]->GetOutput() ); m_Clippers2[index]->SetInsideOut(1); m_Clippers2[index]->Update(); cuttedPlane = m_Clippers2[index]->GetOutput (); if(cuttedPlane->GetNumberOfPoints()) { localStorage->m_OdfsPlanes[index]->RemoveAllInputs(); vtkSmartPointer normals = vtkSmartPointer::New(); normals->SetInputConnection( m_OdfSource->GetOutputPort() ); normals->SplittingOff(); normals->ConsistencyOff(); normals->AutoOrientNormalsOff(); normals->ComputePointNormalsOn(); normals->ComputeCellNormalsOff(); normals->FlipNormalsOff(); normals->NonManifoldTraversalOff(); vtkSmartPointer trans = vtkSmartPointer::New(); trans->SetInputConnection( normals->GetOutputPort() ); trans->SetTransform(m_OdfTransform); vtkSmartPointer glyphGenerator = vtkSmartPointer::New(); glyphGenerator->SetMaximumNumberOfPoints(std::min(m_ShowMaxNumber,(int)cuttedPlane->GetNumberOfPoints())); glyphGenerator->SetRandomMode(0); glyphGenerator->SetUseMaskPoints(1); glyphGenerator->SetSource( trans->GetOutput() ); glyphGenerator->SetInput(cuttedPlane); glyphGenerator->SetColorModeToColorBySource(); glyphGenerator->SetInputArrayToProcess(0,0,0, vtkDataObject::FIELD_ASSOCIATION_POINTS , "vector"); glyphGenerator->SetGeometry(this->GetDataNode()->GetData()->GetGeometry()); glyphGenerator->SetGlyphMethod(&(GlyphMethod),(void *)glyphGenerator); try { glyphGenerator->Update(); } catch( itk::ExceptionObject& err ) { std::cout << err << std::endl; } localStorage->m_OdfsPlanes[index]->AddInput(glyphGenerator->GetOutput()); localStorage->m_OdfsPlanes[index]->Update(); } } localStorage->m_PropAssemblies[index]->VisibilityOn(); if(localStorage->m_PropAssemblies[index]->GetParts()->IsItemPresent(localStorage->m_OdfsActors[index])) localStorage->m_PropAssemblies[index]->RemovePart(localStorage->m_OdfsActors[index]); localStorage->m_OdfsMappers[index]->SetInput(localStorage->m_OdfsPlanes[index]->GetOutput()); localStorage->m_PropAssemblies[index]->AddPart(localStorage->m_OdfsActors[index]); } template bool mitk::OdfVtkMapper2D ::IsVisibleOdfs(mitk::BaseRenderer* renderer) { mitk::Image::Pointer input = const_cast(this->GetInput()); const TimeSlicedGeometry *inputTimeGeometry = input->GetTimeSlicedGeometry(); if(inputTimeGeometry==NULL || inputTimeGeometry->GetTimeSteps()==0 || !inputTimeGeometry->IsValidTime(this->GetTimestep())) return false; if(this->IsPlaneRotated(renderer)) return false; bool retval = false; switch(GetIndex(renderer)) { case 0: - retval = this->IsVisible(renderer, "VisibleOdfs_T"); + GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_T"); break; case 1: - retval = this->IsVisible(renderer, "VisibleOdfs_S"); + GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_S"); break; case 2: - retval = this->IsVisible(renderer, "VisibleOdfs_C"); + GetDataNode()->GetVisibility(retval, renderer, "VisibleOdfs_C"); break; } return retval; } template void mitk::OdfVtkMapper2D ::MitkRenderOverlay(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); } template void mitk::OdfVtkMapper2D ::MitkRenderOpaqueGeometry(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs( renderer )==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) { // adapt cam pos OdfDisplayGeometry dispGeo = MeasureDisplayedGeometry( renderer); this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); } } template void mitk::OdfVtkMapper2D ::MitkRenderTranslucentGeometry(mitk::BaseRenderer* renderer) { if ( this->IsVisibleOdfs(renderer)==false ) return; if ( this->GetVtkProp(renderer)->GetVisibility() ) this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); } template void mitk::OdfVtkMapper2D ::Update(mitk::BaseRenderer* renderer) { - if ( !this->IsVisible( renderer ) ) - return; + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible ) return; mitk::Image::Pointer input = const_cast( this->GetInput() ); if ( input.IsNull() ) return ; std::string classname("TensorImage"); if(classname.compare(input->GetNameOfClass())==0) m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); std::string qclassname("QBallImage"); if(qclassname.compare(input->GetNameOfClass())==0) m_VtkImage = dynamic_cast( this->GetInput() )->GetNonRgbVtkImageData(); if( m_VtkImage ) { // make sure, that we have point data with more than 1 component (as vectors) vtkPointData* pointData = m_VtkImage->GetPointData(); if ( pointData == NULL ) { itkWarningMacro( << "m_VtkImage->GetPointData() returns NULL!" ); return ; } if ( pointData->GetNumberOfArrays() == 0 ) { itkWarningMacro( << "m_VtkImage->GetPointData()->GetNumberOfArrays() is 0!" ); return ; } else if ( pointData->GetArray(0)->GetNumberOfComponents() != N && pointData->GetArray(0)->GetNumberOfComponents() != 6 /*for tensor visualization*/) { itkWarningMacro( << "number of components != number of directions in ODF!" ); return; } else if ( pointData->GetArrayName( 0 ) == NULL ) { m_VtkImage->GetPointData()->GetArray(0)->SetName("vector"); } GenerateDataForRenderer(renderer); } else { itkWarningMacro( << "m_VtkImage is NULL!" ); return ; } } template void mitk::OdfVtkMapper2D ::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); OdfDisplayGeometry dispGeo = MeasureDisplayedGeometry( renderer); if ( (localStorage->m_LastUpdateTime >= m_DataNode->GetMTime()) //was the node modified? && (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList()->GetMTime()) //was a property modified? && (localStorage->m_LastUpdateTime >= m_DataNode->GetPropertyList(renderer)->GetMTime()) && dispGeo.Equals(m_LastDisplayGeometry)) return; localStorage->m_LastUpdateTime.Modified(); if(!IsVisibleOdfs(renderer)) { localStorage->m_OdfsActors[0]->VisibilityOff(); localStorage->m_OdfsActors[1]->VisibilityOff(); localStorage->m_OdfsActors[2]->VisibilityOff(); } else { localStorage->m_OdfsActors[0]->VisibilityOn(); localStorage->m_OdfsActors[1]->VisibilityOn(); localStorage->m_OdfsActors[2]->VisibilityOn(); m_OdfSource->SetAdditionalScale(GetMinImageSpacing(GetIndex(renderer))); ApplyPropertySettings(); Slice(renderer, dispGeo); m_LastDisplayGeometry = dispGeo; } } template double mitk::OdfVtkMapper2D::GetMinImageSpacing( int index ) { // Spacing adapted scaling double spacing[3]; m_VtkImage->GetSpacing(spacing); double min; if(index==0) { min = spacing[0]; min = min > spacing[1] ? spacing[1] : min; } if(index==1) { min = spacing[1]; min = min > spacing[2] ? spacing[2] : min; } if(index==2) { min = spacing[0]; min = min > spacing[2] ? spacing[2] : min; } return min; } template void mitk::OdfVtkMapper2D ::ApplyPropertySettings() { this->GetDataNode()->GetFloatProperty( "Scaling", m_Scaling ); this->GetDataNode()->GetIntProperty( "ShowMaxNumber", m_ShowMaxNumber ); OdfNormalizationMethodProperty* nmp = dynamic_cast(this->GetDataNode()->GetProperty( "Normalization" )); if(nmp) m_Normalization = nmp->GetNormalization(); OdfScaleByProperty* sbp = dynamic_cast(this->GetDataNode()->GetProperty( "ScaleBy" )); if(sbp) m_ScaleBy = sbp->GetScaleBy(); this->GetDataNode()->GetFloatProperty( "IndexParam1", m_IndexParam1); this->GetDataNode()->GetFloatProperty( "IndexParam2", m_IndexParam2); } template bool mitk::OdfVtkMapper2D ::IsPlaneRotated(mitk::BaseRenderer* renderer) { Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); vtkFloatingPointType vnormal[ 3 ]; Vector3D normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); vnl2vtk( normal.Get_vnl_vector(), vnormal ); vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); vtkSmartPointer inversetransform = vtkSmartPointer::New(); inversetransform->Identity(); inversetransform->Concatenate(vtktransform->GetLinearInverse()); double* n = inversetransform->TransformNormal(vnormal); int nonZeros = 0; for (int j=0; j<3; j++) { if (fabs(n[j])>mitk::eps){ nonZeros++; } } if(nonZeros>1) return true; return false; } template void mitk::OdfVtkMapper2D ::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* /*renderer*/, bool /*overwrite*/) { node->SetProperty( "ShowMaxNumber", mitk::IntProperty::New( 150 ) ); node->SetProperty( "Scaling", mitk::FloatProperty::New( 1.0 ) ); node->SetProperty( "Normalization", mitk::OdfNormalizationMethodProperty::New()); node->SetProperty( "ScaleBy", mitk::OdfScaleByProperty::New()); node->SetProperty( "IndexParam1", mitk::FloatProperty::New(2)); node->SetProperty( "IndexParam2", mitk::FloatProperty::New(1)); node->SetProperty( "visible", mitk::BoolProperty::New( true ) ); node->SetProperty( "VisibleOdfs_T", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_C", mitk::BoolProperty::New( false ) ); node->SetProperty( "VisibleOdfs_S", mitk::BoolProperty::New( false ) ); node->SetProperty ("layer", mitk::IntProperty::New(100)); node->SetProperty( "DoRefresh", mitk::BoolProperty::New( true ) ); } #endif // __mitkOdfVtkMapper2D_txx__ diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkPlanarFigureMapper3D.cpp b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkPlanarFigureMapper3D.cpp index ac70a28948..825d657a22 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkPlanarFigureMapper3D.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkPlanarFigureMapper3D.cpp @@ -1,161 +1,121 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPlanarFigureMapper3D.h" #include #include #include #include mitk::PlanarFigureMapper3D::PlanarFigureMapper3D() : m_points(vtkPoints::New()) , m_polygon(vtkPolygon::New()) , m_polygonPolyData(vtkPolyData::New()) , m_polygonsCell(vtkCellArray::New()) , m_VtkPolygonDataMapperGL(vtkOpenGLPolyDataMapper::New()) , m_PolygonActor(vtkOpenGLActor::New()) , m_PolygonAssembly(vtkPropAssembly::New()) { } //template mitk::PlanarFigureMapper3D::~PlanarFigureMapper3D() { } const mitk::PlanarFigure* mitk::PlanarFigureMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } -/* - This method is called once the mapper gets new input, - for UI rotation or changes in colorcoding this method is NOT called - */ -void mitk::PlanarFigureMapper3D::GenerateData() + +void mitk::PlanarFigureMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { try { - mitk::PlanarFigure* pf = dynamic_cast< mitk::PlanarFigure* > (this->GetData()); + mitk::PlanarFigure* pf = dynamic_cast< mitk::PlanarFigure* > (GetDataNode()->GetData()); const mitk::Geometry2D* pfgeometry = pf->GetGeometry2D(); const mitk::PlaneGeometry* planeGeo = dynamic_cast(pfgeometry); mitk::Point3D wp; - mitk::PlanarFigure::PolyLineType line = pf->GetPolyLine(0); if (line.size() <= 2) return; m_points->SetNumberOfPoints(line.size()); m_polygon->GetPointIds()->SetNumberOfIds(line.size()); int i=0; for (mitk::PlanarFigure::PolyLineType::iterator it = line.begin(); it!=line.end(); ++it) { mitk::PlanarFigure::PolyLineElement elem = *it; planeGeo->Map(elem.Point, wp); m_points->InsertPoint(i,(double)wp[0], (double)wp[1], (double)wp[2] ); m_polygon->GetPointIds()->SetId(i, i); i++; } m_polygonsCell->Reset(); m_polygonsCell->InsertNextCell(m_polygon); m_polygonPolyData->SetPoints(m_points); m_polygonPolyData->SetPolys(m_polygonsCell); m_VtkPolygonDataMapperGL->SetInput(m_polygonPolyData); m_PolygonActor->SetMapper(m_VtkPolygonDataMapperGL); m_PolygonAssembly->AddPart(m_PolygonActor); - m_VtkPolygonDataMapperGL->Modified(); - } - catch(...) - { - - } -} - -void mitk::PlanarFigureMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) -{ - try - { - mitk::PlanarFigure* pf = dynamic_cast< mitk::PlanarFigure* > (this->GetData()); - - const mitk::Geometry2D* pfgeometry = pf->GetGeometry2D(); - const mitk::PlaneGeometry* planeGeo = dynamic_cast(pfgeometry); - mitk::Point3D wp; - mitk::PlanarFigure::PolyLineType line = pf->GetPolyLine(0); - - if (line.size() <= 2) - return; - - m_points->SetNumberOfPoints(line.size()); - m_polygon->GetPointIds()->SetNumberOfIds(line.size()); - - int i=0; - for (mitk::PlanarFigure::PolyLineType::iterator it = line.begin(); it!=line.end(); ++it) - { - mitk::PlanarFigure::PolyLineElement elem = *it; - planeGeo->Map(elem.Point, wp); - - m_points->InsertPoint(i,(double)wp[0], (double)wp[1], (double)wp[2] ); - m_polygon->GetPointIds()->SetId(i, i); - i++; - } - //updates all polygon pipeline m_VtkPolygonDataMapperGL->Modified(); float polyOpaq; this->GetDataNode()->GetOpacity(polyOpaq, NULL); m_PolygonActor->GetProperty()->SetOpacity((double) polyOpaq); float temprgb[3]; this->GetDataNode()->GetColor( temprgb, NULL ); double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] }; m_PolygonActor->GetProperty()->SetColor(trgb); } catch (...) { } } void mitk::PlanarFigureMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { Superclass::SetDefaultProperties(node, renderer, overwrite); } vtkProp* mitk::PlanarFigureMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { return m_PolygonAssembly; } void mitk::PlanarFigureMapper3D::UpdateVtkObjects() { } void mitk::PlanarFigureMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) { } diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkPlanarFigureMapper3D.h b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkPlanarFigureMapper3D.h index e6a21daed5..334e883b6d 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkPlanarFigureMapper3D.h +++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkPlanarFigureMapper3D.h @@ -1,76 +1,75 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef PlanarFigureMapper3D_H #define PlanarFigureMapper3D_H #include -#include +#include #include #include #include #include #include #include #include #include #include namespace mitk { //##Documentation //## @brief 3D mapper for planar figures //## @ingroup Mapper // template - class PlanarFigureMapper3D : public VtkMapper3D + class PlanarFigureMapper3D : public VtkMapper { public: - mitkClassMacro(PlanarFigureMapper3D, VtkMapper3D) + mitkClassMacro(PlanarFigureMapper3D, VtkMapper) itkNewMacro(Self) const mitk::PlanarFigure* GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); //looks like depricated.. should be replaced bz GetViewProp() static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); - virtual void GenerateData(); protected: PlanarFigureMapper3D(); virtual ~PlanarFigureMapper3D(); void UpdateVtkObjects(); vtkSmartPointer m_points; vtkSmartPointer m_polygon; vtkSmartPointer m_polygonPolyData; vtkSmartPointer m_polygonsCell; vtkSmartPointer m_VtkPolygonDataMapperGL; vtkSmartPointer m_PolygonActor; vtkSmartPointer m_PolygonAssembly; }; } // namespace mitk #endif /* FiberBundleMapper3D_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.cpp b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.cpp index 6c82f14860..1e45c857ac 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.cpp +++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.cpp @@ -1,211 +1,207 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkVectorImageVtkGlyphMapper3D.h" #include #include #include #include #include #include #include #include #include #include #include /* * Constructor. Doesn't do anything... */ mitk::VectorImageVtkGlyphMapper3D::VectorImageVtkGlyphMapper3D() { m_RandomMode = true; m_UseMaskPoints = true; m_MaximumNumberOfPoints = 5000; m_GlyphType = ArrowGlyph; m_Glyph3DGenerator = vtkMaskedGlyph3D::New(); m_Glyph3DMapper = vtkPolyDataMapper::New(); m_Glyph3DActor = vtkActor::New(); } vtkProp* mitk::VectorImageVtkGlyphMapper3D::GetVtkProp(mitk::BaseRenderer* /*renderer*/) { return m_Glyph3DActor; } /* * Destructor */ mitk::VectorImageVtkGlyphMapper3D::~VectorImageVtkGlyphMapper3D() { if ( m_Glyph3DMapper != NULL ) m_Glyph3DMapper->Delete(); if ( m_Glyph3DGenerator != NULL ) m_Glyph3DGenerator->Delete(); } - /* * Generate a vtkPolyData by creating vectors as glyphs +* This method is called, each time a specific renderer is updated. */ -void mitk::VectorImageVtkGlyphMapper3D::GenerateData() +void mitk::VectorImageVtkGlyphMapper3D::GenerateDataForRenderer( mitk::BaseRenderer* renderer ) { // // get the input image... // mitk::Image::Pointer mitkImage = this->GetInput(); if ( mitkImage.GetPointer() == NULL ) { itkWarningMacro( << "VectorImage is null !" ); return ; } // // make sure, that the input image is an vector image // if ( mitkImage->GetPixelType().GetNumberOfComponents() <= 1 ) { itkWarningMacro( << "VectorImage has only one scalar component!" ); return ; } vtkImageData* vtkImage = mitkImage->GetVtkImageData(); // // make sure, that we have point data with more than 1 component (as vectors) // vtkPointData* pointData = vtkImage->GetPointData(); if ( pointData == NULL ) { itkWarningMacro( << "vtkImage->GetPointData() returns NULL!" ); return ; } if ( pointData->GetNumberOfArrays() == 0 ) { itkWarningMacro( << "vtkImage->GetPointData()->GetNumberOfArrays() is 0!" ); return ; } else if ( pointData->GetArrayName( 0 ) == NULL ) { vtkImage->GetPointData() ->GetArray( 0 ) ->SetName( "vector" ); } if ( vtkImage->GetNumberOfPoints() != 0 ) { // // create the glyph, which has to be shown at each point // of the masked image // vtkPolyData* glyph; if ( m_GlyphType == LineGlyph ) { vtkLineSource * lineSource = vtkLineSource::New(); lineSource->Update(); glyph = lineSource->GetOutput(); } else if ( m_GlyphType == ArrowGlyph ) { vtkArrowSource * arrowSource = vtkArrowSource::New(); arrowSource->Update(); glyph = arrowSource->GetOutput(); } else { // Use a vtkLineSource as default, if the GlyphType is // unknown itkWarningMacro( << "unknown glyph type!" ); vtkLineSource * lineSource = vtkLineSource::New(); lineSource->Update(); glyph = lineSource->GetOutput(); } m_RandomMode = false; m_UseMaskPoints = false; m_MaximumNumberOfPoints = 80*80*80; // // set up the actual glyphing filter // m_Glyph3DGenerator->SetSource( glyph ); m_Glyph3DGenerator->SetInput( vtkImage ); //m_Glyph3DGenerator->SetInputConnection(m_Cutter->GetOutputPort()); m_Glyph3DGenerator->SetInputArrayToProcess (1, 0,0, vtkDataObject::FIELD_ASSOCIATION_POINTS , "vector"); //m_Glyph3DGenerator->SelectInputVectors( vtkImage->GetPointData() ->GetArray( 0 ) ->GetName() ); m_Glyph3DGenerator->OrientOn(); m_Glyph3DGenerator->SetVectorModeToUseVector(); m_Glyph3DGenerator->SetScaleFactor( 0.00392156862745 ); m_Glyph3DGenerator->SetScaleModeToScaleByVector(); m_Glyph3DGenerator->SetUseMaskPoints( m_UseMaskPoints ); m_Glyph3DGenerator->SetRandomMode( m_RandomMode ); m_Glyph3DGenerator->SetMaximumNumberOfPoints( m_MaximumNumberOfPoints ); m_Glyph3DGenerator->Update(); m_Glyph3DMapper->SetInput( m_Glyph3DGenerator->GetOutput() ); m_Glyph3DActor->SetMapper( m_Glyph3DMapper ); if (GetDataNode()->GetProperty("LookupTable")) { mitk::LookupTable::Pointer mitkLookupTable = mitk::LookupTable::New(); m_Glyph3DMapper->Update(); mitkLookupTable->SetVtkLookupTable(dynamic_cast(m_Glyph3DMapper->GetLookupTable())); mitk::LookupTableProperty::Pointer LookupTableProp = mitk::LookupTableProperty::New( mitkLookupTable ); GetDataNode()->SetProperty( "LookupTable", LookupTableProp ); } else { mitk::LookupTableProperty::Pointer mitkLutProp = dynamic_cast(GetDataNode()->GetProperty("LookupTable")); if (mitkLutProp.IsNotNull()) m_Glyph3DMapper->SetLookupTable( mitkLutProp->GetLookupTable()->GetVtkLookupTable() ); } //vtkDataSetWriter* writer = vtkDataSetWriter::New(); //writer->SetInput( vtkImage ); //writer->SetFileName( "out.vtk" ); //writer->Update(); } -} + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); -/* -* This method is called, each time a specific renderer is updated. -*/ -void mitk::VectorImageVtkGlyphMapper3D::GenerateDataForRenderer( mitk::BaseRenderer* renderer ) -{ - if ( IsVisible( renderer ) == false ) + if ( !visible ) { if ( m_Glyph3DActor != NULL ) m_Glyph3DActor->VisibilityOff(); return ; } else { if ( m_Glyph3DActor != NULL ) m_Glyph3DActor->VisibilityOn(); } } /* * Returns the input data object of the given filter. In this * case, a mitk::Image is returned. */ mitk::Image* mitk::VectorImageVtkGlyphMapper3D::GetInput() { - return const_cast( dynamic_cast( this->GetData() ) ); + return const_cast( dynamic_cast( GetDataNode()->GetData() ) ); } diff --git a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.h b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.h index f75dd01ea8..3c96509165 100644 --- a/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.h +++ b/Modules/DiffusionImaging/DiffusionCore/Rendering/mitkVectorImageVtkGlyphMapper3D.h @@ -1,100 +1,96 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_VECTOR_IMAGE_VTK_MAPPER_3D__H #define _MITK_VECTOR_IMAGE_VTK_MAPPER_3D__H #include "DiffusionCoreExports.h" -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include "mitkImage.h" class vtkMaskedGlyph3D; class vtkActor; class vtkPolyDataMapper; class vtkMaskPoints; namespace mitk { -class DiffusionCore_EXPORT VectorImageVtkGlyphMapper3D : public VtkMapper3D +class DiffusionCore_EXPORT VectorImageVtkGlyphMapper3D : public VtkMapper { public: - mitkClassMacro( VectorImageVtkGlyphMapper3D, VtkMapper3D ); + mitkClassMacro( VectorImageVtkGlyphMapper3D, VtkMapper ); itkNewMacro( Self ); enum GlyphType {LineGlyph, ArrowGlyph}; itkSetMacro(MaximumNumberOfPoints, unsigned int); itkGetMacro(MaximumNumberOfPoints, unsigned int); itkSetMacro(UseMaskPoints, bool); itkGetMacro(UseMaskPoints, bool); itkBooleanMacro(UseMaskPoints); itkSetMacro(RandomMode, bool); itkGetMacro(RandomMode, bool); itkBooleanMacro(RandomMode); virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); protected: /** * Constructor. Doesn't do anything... */ VectorImageVtkGlyphMapper3D(); /** * Destructor */ virtual ~VectorImageVtkGlyphMapper3D(); /** * Generate a vtkPolyData by creating vectors as glyphs - */ - virtual void GenerateData(); - - /** * This method is called, each time a specific renderer is updated. */ virtual void GenerateDataForRenderer( mitk::BaseRenderer* renderer ); /** * Returns the input data object of the given filter. In this * case, a mitk::Image is returned. */ Image* GetInput(); vtkMaskedGlyph3D* m_Glyph3DGenerator; vtkActor* m_Glyph3DActor; vtkPolyDataMapper* m_Glyph3DMapper; GlyphType m_GlyphType; unsigned int m_MaximumNumberOfPoints; bool m_UseMaskPoints; bool m_RandomMode; }; } //end of namespace mitk #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp index 66891575b5..8b18603b14 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.cpp @@ -1,631 +1,624 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "itkTractsToDWIImageFilter.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace itk { TractsToDWIImageFilter::TractsToDWIImageFilter() : m_CircleDummy(false) , m_VolumeAccuracy(10) , m_Upsampling(1) , m_NumberOfRepetitions(1) - , m_EnforcePureFiberVoxels(true) - , m_InterpolationShrink(5) + , m_EnforcePureFiberVoxels(false) + , m_InterpolationShrink(10) + , m_FiberRadius(20) + , m_SignalScale(300) { m_Spacing.Fill(2.5); m_Origin.Fill(0.0); m_DirectionMatrix.SetIdentity(); m_ImageRegion.SetSize(0, 10); m_ImageRegion.SetSize(1, 10); m_ImageRegion.SetSize(2, 10); } TractsToDWIImageFilter::~TractsToDWIImageFilter() { } std::vector< TractsToDWIImageFilter::DoubleDwiType::Pointer > TractsToDWIImageFilter::AddKspaceArtifacts( std::vector< DoubleDwiType::Pointer >& images ) { // create slice object SliceType::Pointer slice = SliceType::New(); ImageRegion<2> region; region.SetSize(0, m_UpsampledImageRegion.GetSize()[0]); region.SetSize(1, m_UpsampledImageRegion.GetSize()[1]); slice->SetLargestPossibleRegion( region ); slice->SetBufferedRegion( region ); slice->SetRequestedRegion( region ); slice->Allocate(); boost::progress_display disp(images.size()*images[0]->GetVectorLength()*images[0]->GetLargestPossibleRegion().GetSize(2)); std::vector< DoubleDwiType::Pointer > outImages; for (int i=0; iSetSpacing( m_Spacing ); newImage->SetOrigin( m_Origin ); newImage->SetDirection( m_DirectionMatrix ); newImage->SetLargestPossibleRegion( m_ImageRegion ); newImage->SetBufferedRegion( m_ImageRegion ); newImage->SetRequestedRegion( m_ImageRegion ); newImage->SetVectorLength( image->GetVectorLength() ); newImage->Allocate(); DiffusionSignalModel* signalModel; if (iGetVectorLength(); g++) for (int z=0; zGetLargestPossibleRegion().GetSize(2); z++) { ++disp; // extract slice from channel g for (int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; SliceType::PixelType pix2D = image->GetPixel(index3D)[g]; slice->SetPixel(index2D, pix2D); } // fourier transform slice itk::FFTRealToComplexConjugateImageFilter< SliceType::PixelType, 2 >::Pointer fft = itk::FFTRealToComplexConjugateImageFilter< SliceType::PixelType, 2 >::New(); fft->SetInput(slice); fft->Update(); ComplexSliceType::Pointer fSlice = fft->GetOutput(); fSlice = RearrangeSlice(fSlice); // add artifacts for (int a=0; aSetRelaxationT2(signalModel->GetRelaxationT2()); + m_KspaceArtifacts.at(a)->SetT2(signalModel->GetT2()); fSlice = m_KspaceArtifacts.at(a)->AddArtifact(fSlice); } // save k-space slice of s0 image if (g==0) - for (int y=0; yGetLargestPossibleRegion().GetSize(1); y++) - for (int x=0; xGetLargestPossibleRegion().GetSize(0); x++) - { - DoubleDwiType::IndexType index3D; - index3D[0]=x; index3D[1]=y; index3D[2]=z; - SliceType::IndexType index2D; - index2D[0]=x; index2D[1]=y; - double kpix = sqrt(fSlice->GetPixel(index2D).real()*fSlice->GetPixel(index2D).real()+fSlice->GetPixel(index2D).imag()*fSlice->GetPixel(index2D).imag()); - m_KspaceImage->SetPixel(index3D, kpix); - } + for (int y=0; yGetLargestPossibleRegion().GetSize(1); y++) + for (int x=0; xGetLargestPossibleRegion().GetSize(0); x++) + { + DoubleDwiType::IndexType index3D; + index3D[0]=x; index3D[1]=y; index3D[2]=z; + SliceType::IndexType index2D; + index2D[0]=x; index2D[1]=y; + double kpix = sqrt(fSlice->GetPixel(index2D).real()*fSlice->GetPixel(index2D).real()+fSlice->GetPixel(index2D).imag()*fSlice->GetPixel(index2D).imag()); + m_KspaceImage->SetPixel(index3D, kpix); + } // inverse fourier transform slice SliceType::Pointer newSlice; itk::FFTComplexConjugateToRealImageFilter< SliceType::PixelType, 2 >::Pointer ifft = itk::FFTComplexConjugateToRealImageFilter< SliceType::PixelType, 2 >::New(); ifft->SetInput(fSlice); ifft->Update(); newSlice = ifft->GetOutput(); // put slice back into channel g for (int y=0; yGetLargestPossibleRegion().GetSize(1); y++) for (int x=0; xGetLargestPossibleRegion().GetSize(0); x++) { DoubleDwiType::IndexType index3D; index3D[0]=x; index3D[1]=y; index3D[2]=z; DoubleDwiType::PixelType pix3D = newImage->GetPixel(index3D); SliceType::IndexType index2D; index2D[0]=x; index2D[1]=y; pix3D[g] = newSlice->GetPixel(index2D); newImage->SetPixel(index3D, pix3D); } } outImages.push_back(newImage); } return outImages; } TractsToDWIImageFilter::ComplexSliceType::Pointer TractsToDWIImageFilter::RearrangeSlice(ComplexSliceType::Pointer slice) { ImageRegion<2> region = slice->GetLargestPossibleRegion(); ComplexSliceType::Pointer rearrangedSlice = ComplexSliceType::New(); rearrangedSlice->SetLargestPossibleRegion( region ); rearrangedSlice->SetBufferedRegion( region ); rearrangedSlice->SetRequestedRegion( region ); rearrangedSlice->Allocate(); int xHalf = region.GetSize(0)/2; int yHalf = region.GetSize(1)/2; for (int y=0; y pix = slice->GetPixel(idx); if( idx[0] < xHalf ) idx[0] = idx[0] + xHalf; else idx[0] = idx[0] - xHalf; if( idx[1] < yHalf ) idx[1] = idx[1] + yHalf; else idx[1] = idx[1] - yHalf; rearrangedSlice->SetPixel(idx, pix); } return rearrangedSlice; } void TractsToDWIImageFilter::GenerateData() { // check input data if (m_FiberBundle.IsNull()) itkExceptionMacro("Input fiber bundle is NULL!"); int numFibers = m_FiberBundle->GetNumFibers(); if (numFibers<=0) itkExceptionMacro("Input fiber bundle contains no fibers!"); if (m_FiberModels.empty()) itkExceptionMacro("No diffusion model for fiber compartments defined!"); if (m_NonFiberModels.empty()) itkExceptionMacro("No diffusion model for non-fiber compartments defined!"); int baselineIndex = m_FiberModels[0]->GetFirstBaselineIndex(); if (baselineIndex<0) itkExceptionMacro("No baseline index found!"); // determine k-space undersampling for (int i=0; i*>(m_KspaceArtifacts.at(i)) ) m_Upsampling = dynamic_cast*>(m_KspaceArtifacts.at(i))->GetKspaceCropping(); if (m_Upsampling<1) m_Upsampling = 1; if (m_TissueMask.IsNotNull()) { // use input tissue mask m_Spacing = m_TissueMask->GetSpacing(); m_Origin = m_TissueMask->GetOrigin(); m_DirectionMatrix = m_TissueMask->GetDirection(); m_ImageRegion = m_TissueMask->GetLargestPossibleRegion(); if (m_Upsampling>1) { ImageRegion<3> region = m_ImageRegion; region.SetSize(0, m_ImageRegion.GetSize(0)*m_Upsampling); region.SetSize(1, m_ImageRegion.GetSize(1)*m_Upsampling); mitk::Vector3D spacing = m_Spacing; spacing[0] /= m_Upsampling; spacing[1] /= m_Upsampling; itk::RescaleIntensityImageFilter::Pointer rescaler = itk::RescaleIntensityImageFilter::New(); rescaler->SetInput(0,m_TissueMask); rescaler->SetOutputMaximum(100); rescaler->SetOutputMinimum(0); rescaler->Update(); itk::ResampleImageFilter::Pointer resampler = itk::ResampleImageFilter::New(); resampler->SetInput(rescaler->GetOutput()); resampler->SetOutputParametersFromImage(m_TissueMask); resampler->SetSize(region.GetSize()); resampler->SetOutputSpacing(spacing); resampler->Update(); m_TissueMask = resampler->GetOutput(); } MITK_INFO << "Using tissue mask"; } // initialize output dwi image OutputImageType::Pointer outImage = OutputImageType::New(); outImage->SetSpacing( m_Spacing ); outImage->SetOrigin( m_Origin ); outImage->SetDirection( m_DirectionMatrix ); outImage->SetLargestPossibleRegion( m_ImageRegion ); outImage->SetBufferedRegion( m_ImageRegion ); outImage->SetRequestedRegion( m_ImageRegion ); outImage->SetVectorLength( m_FiberModels[0]->GetNumGradients() ); outImage->Allocate(); OutputImageType::PixelType temp; temp.SetSize(m_FiberModels[0]->GetNumGradients()); temp.Fill(0.0); outImage->FillBuffer(temp); // is input slize size a power of two? int x=2; int y=2; while (x " << x; m_ImageRegion.SetSize(0, x); } if (y!=m_ImageRegion.GetSize(1)) { MITK_INFO << "Adjusting image height: " << m_ImageRegion.GetSize(1) << " --> " << y; m_ImageRegion.SetSize(1, y); } // initialize k-space image m_KspaceImage = ItkDoubleImgType::New(); m_KspaceImage->SetSpacing( m_Spacing ); m_KspaceImage->SetOrigin( m_Origin ); m_KspaceImage->SetDirection( m_DirectionMatrix ); m_KspaceImage->SetLargestPossibleRegion( m_ImageRegion ); m_KspaceImage->SetBufferedRegion( m_ImageRegion ); m_KspaceImage->SetRequestedRegion( m_ImageRegion ); m_KspaceImage->Allocate(); m_KspaceImage->FillBuffer(0); // apply undersampling to image parameters m_UpsampledSpacing = m_Spacing; m_UpsampledImageRegion = m_ImageRegion; m_UpsampledSpacing[0] /= m_Upsampling; m_UpsampledSpacing[1] /= m_Upsampling; m_UpsampledImageRegion.SetSize(0, m_ImageRegion.GetSize()[0]*m_Upsampling); m_UpsampledImageRegion.SetSize(1, m_ImageRegion.GetSize()[1]*m_Upsampling); // everything from here on is using the upsampled image parameters!!! if (m_TissueMask.IsNull()) { m_TissueMask = ItkUcharImgType::New(); m_TissueMask->SetSpacing( m_UpsampledSpacing ); m_TissueMask->SetOrigin( m_Origin ); m_TissueMask->SetDirection( m_DirectionMatrix ); m_TissueMask->SetLargestPossibleRegion( m_UpsampledImageRegion ); m_TissueMask->SetBufferedRegion( m_UpsampledImageRegion ); m_TissueMask->SetRequestedRegion( m_UpsampledImageRegion ); m_TissueMask->Allocate(); m_TissueMask->FillBuffer(1); } // resample fiber bundle for sufficient voxel coverage + double segmentVolume = 1; float minSpacing = 1; if(m_UpsampledSpacing[0]GetFiberSampling()<=0 || 10/m_FiberBundle->GetFiberSampling()>minSpacing*0.5/m_VolumeAccuracy) - { - fiberBundle = m_FiberBundle->GetDeepCopy(); - fiberBundle->ResampleFibers(minSpacing/m_VolumeAccuracy); - } + FiberBundleType fiberBundle = m_FiberBundle->GetDeepCopy(); + fiberBundle->ResampleFibers(minSpacing/m_VolumeAccuracy); + double mmRadius = m_FiberRadius/1000; + if (mmRadius>0) + segmentVolume = M_PI*mmRadius*mmRadius*minSpacing/m_VolumeAccuracy; // generate double images to wokr with because we don't want to lose precision // we use a separate image for each compartment model std::vector< DoubleDwiType::Pointer > compartments; for (int i=0; iSetSpacing( m_UpsampledSpacing ); doubleDwi->SetOrigin( m_Origin ); doubleDwi->SetDirection( m_DirectionMatrix ); doubleDwi->SetLargestPossibleRegion( m_UpsampledImageRegion ); doubleDwi->SetBufferedRegion( m_UpsampledImageRegion ); doubleDwi->SetRequestedRegion( m_UpsampledImageRegion ); doubleDwi->SetVectorLength( m_FiberModels[0]->GetNumGradients() ); doubleDwi->Allocate(); DoubleDwiType::PixelType pix; pix.SetSize(m_FiberModels[0]->GetNumGradients()); pix.Fill(0.0); doubleDwi->FillBuffer(pix); compartments.push_back(doubleDwi); } if (m_CircleDummy) { for (int i=0; iGetNumGradients()); pix.Fill(1); DoubleDwiType::Pointer doubleDwi = compartments.at(i); ImageRegion<3> region = doubleDwi->GetLargestPossibleRegion(); ImageRegionIterator it(doubleDwi, region); while(!it.IsAtEnd()) { DoubleDwiType::IndexType index = it.GetIndex(); double t = region.GetSize(0)/2; double d1 = index[0]-t+0.5; t = region.GetSize(1)/2; double d2 = index[1]-t+0.5; if (sqrt(d1*d1+d2*d2)<20*m_Upsampling) it.Set(pix); ++it; } } } else { double interpFact = 2*atan(-0.5*m_InterpolationShrink); + double maxVolume = 0; vtkSmartPointer fiberPolyData = fiberBundle->GetFiberPolyData(); vtkSmartPointer vLines = fiberPolyData->GetLines(); vLines->InitTraversal(); MITK_INFO << "Generating signal of " << m_FiberModels.size() << " fiber compartments"; - double maxFiberDensity = 0; boost::progress_display disp(numFibers); for( int i=0; iGetNextCell ( numPoints, points ); if (numPoints<2) continue; for( int j=0; jGetPoint(points[j]); itk::Point vertex = GetItkPoint(temp); itk::Vector v = GetItkVector(temp); itk::Vector dir(3); if (jGetPoint(points[j+1]))-v; else dir = v-GetItkVector(fiberPolyData->GetPoint(points[j-1])); itk::Index<3> idx; itk::ContinuousIndex contIndex; m_TissueMask->TransformPhysicalPointToIndex(vertex, idx); m_TissueMask->TransformPhysicalPointToContinuousIndex(vertex, contIndex); double frac_x = contIndex[0] - idx[0]; double frac_y = contIndex[1] - idx[1]; double frac_z = contIndex[2] - idx[2]; if (frac_x<0) { idx[0] -= 1; frac_x += 1; } if (frac_y<0) { idx[1] -= 1; frac_y += 1; } if (frac_z<0) { idx[2] -= 1; frac_z += 1; } frac_x = atan((0.5-frac_x)*m_InterpolationShrink)/interpFact + 0.5; frac_y = atan((0.5-frac_y)*m_InterpolationShrink)/interpFact + 0.5; frac_z = atan((0.5-frac_z)*m_InterpolationShrink)/interpFact + 0.5; // use trilinear interpolation itk::Index<3> newIdx; for (int x=0; x<2; x++) { frac_x = 1-frac_x; for (int y=0; y<2; y++) { frac_y = 1-frac_y; for (int z=0; z<2; z++) { frac_z = 1-frac_z; newIdx[0] = idx[0]+x; newIdx[1] = idx[1]+y; newIdx[2] = idx[2]+z; double frac = frac_x*frac_y*frac_z; // is position valid? if (!m_TissueMask->GetLargestPossibleRegion().IsInside(newIdx) || m_TissueMask->GetPixel(newIdx)<=0) continue; // generate signal for each fiber compartment for (int k=0; kSetFiberDirection(dir); - doubleDwi->SetPixel(newIdx, doubleDwi->GetPixel(newIdx) + frac*m_FiberModels[k]->SimulateMeasurement()); - DoubleDwiType::PixelType pix = doubleDwi->GetPixel(newIdx); - if (pix[baselineIndex]>maxFiberDensity) - maxFiberDensity = pix[baselineIndex]; + pix += segmentVolume*frac*m_FiberModels[k]->SimulateMeasurement(); + doubleDwi->SetPixel(newIdx, pix ); + if (pix[baselineIndex]>maxVolume) + maxVolume = pix[baselineIndex]; } } } } } } MITK_INFO << "Generating signal of " << m_NonFiberModels.size() << " non-fiber compartments"; - boost::progress_display disp2(m_NonFiberModels.size()*compartments.at(0)->GetLargestPossibleRegion().GetNumberOfPixels()); - for (int i=0; i it(doubleDwi, doubleDwi->GetLargestPossibleRegion()); - while(!it.IsAtEnd()) - { - ++disp2; - DoubleDwiType::IndexType index = it.GetIndex(); - if (m_TissueMask->GetLargestPossibleRegion().IsInside(index) && m_TissueMask->GetPixel(index)>0) - doubleDwi->SetPixel(index, doubleDwi->GetPixel(index) + m_NonFiberModels[i]->SimulateMeasurement()); - ++it; - } - } - - MITK_INFO << "Adjusting compartment signal intensities according to volume fraction"; ImageRegionIterator it3(m_TissueMask, m_TissueMask->GetLargestPossibleRegion()); boost::progress_display disp3(m_TissueMask->GetLargestPossibleRegion().GetNumberOfPixels()); + double voxelVolume = m_UpsampledSpacing[0]*m_UpsampledSpacing[1]*m_UpsampledSpacing[2]; + + double fact = 1; + if (m_FiberRadius<0.0001) + fact = voxelVolume/maxVolume; + while(!it3.IsAtEnd()) { ++disp3; DoubleDwiType::IndexType index = it3.GetIndex(); if (it3.Get()>0) { - // compartment weights are calculated according to fiber density - double w = compartments.at(0)->GetPixel(index)[baselineIndex]/maxFiberDensity; - if (m_EnforcePureFiberVoxels && w>0) - w = 1; - - // adjust fiber signal + // get fiber volume fraction + double w = 0; for (int i=0; iGetPixel(index); - if (pix[baselineIndex]>0) - pix /= pix[baselineIndex]; - pix *= w/m_FiberModels.size(); - doubleDwi->SetPixel(index, pix); + DoubleDwiType::PixelType pix = compartments.at(i)->GetPixel(index); + if (fact<1) + { + pix *= fact; + compartments.at(i)->SetPixel(index, pix); + } + w += pix[baselineIndex]; } - // adjust non-fiber signal - for (int i=0; ivoxelVolume || w>0 && m_EnforcePureFiberVoxels) // more fiber than space in voxel? { - DoubleDwiType::Pointer doubleDwi = compartments.at(i+m_FiberModels.size()); - DoubleDwiType::PixelType pix = doubleDwi->GetPixel(index); - if (pix[baselineIndex]>0) - pix /= pix[baselineIndex]; - pix *= (1-w)/m_NonFiberModels.size(); - doubleDwi->SetPixel(index, pix); + // adjust fiber signal + for (int i=0; iSetPixel(index, doubleDwi->GetPixel(index)*voxelVolume/w); + } } + else + { + w = voxelVolume-w; // non-fiber volume + // adjust non-fiber signal + for (int i=0; iGetPixel(index) + m_NonFiberModels[i]->SimulateMeasurement()*w/m_NonFiberModels.size(); + doubleDwi->SetPixel(index, pix); + } + } } ++it3; } } // do k-space stuff if (!m_KspaceArtifacts.empty()) MITK_INFO << "Generating k-space artifacts"; else MITK_INFO << "Generating k-space image"; compartments = AddKspaceArtifacts(compartments); MITK_INFO << "Summing compartments and adding noise"; - double correction = m_Upsampling*m_Upsampling; + double correction = m_SignalScale; ///(m_Upsampling*m_Upsampling); ImageRegionIterator it4 (outImage, outImage->GetLargestPossibleRegion()); DoubleDwiType::PixelType signal; signal.SetSize(m_FiberModels[0]->GetNumGradients()); boost::progress_display disp4(outImage->GetLargestPossibleRegion().GetNumberOfPixels()); while(!it4.IsAtEnd()) { ++disp4; DWIImageType::IndexType index = it4.GetIndex(); signal.Fill(0.0); // adjust fiber signal for (int i=0; iGetSignalScale()/correction; - signal += compartments.at(i)->GetPixel(index)*s; - } + signal += compartments.at(i)->GetPixel(index)*correction; // adjust non-fiber signal for (int i=0; iGetSignalScale()/correction; - signal += compartments.at(m_FiberModels.size()+i)->GetPixel(index)*s; - } + signal += compartments.at(m_FiberModels.size()+i)->GetPixel(index)*correction; DoubleDwiType::PixelType accu = signal; accu.Fill(0.0); for (int i=0; iAddNoise(temp); accu += temp; } signal = accu/m_NumberOfRepetitions; for (int i=0; i0) signal[i] = floor(signal[i]+0.5); else signal[i] = ceil(signal[i]-0.5); } it4.Set(signal); ++it4; } this->SetNthOutput(0, outImage); } itk::Point TractsToDWIImageFilter::GetItkPoint(double point[3]) { itk::Point itkPoint; itkPoint[0] = point[0]; itkPoint[1] = point[1]; itkPoint[2] = point[2]; return itkPoint; } itk::Vector TractsToDWIImageFilter::GetItkVector(double point[3]) { itk::Vector itkVector; itkVector[0] = point[0]; itkVector[1] = point[1]; itkVector[2] = point[2]; return itkVector; } vnl_vector_fixed TractsToDWIImageFilter::GetVnlVector(double point[3]) { vnl_vector_fixed vnlVector; vnlVector[0] = point[0]; vnlVector[1] = point[1]; vnlVector[2] = point[2]; return vnlVector; } vnl_vector_fixed TractsToDWIImageFilter::GetVnlVector(Vector& vector) { vnl_vector_fixed vnlVector; vnlVector[0] = vector[0]; vnlVector[1] = vector[1]; vnlVector[2] = vector[2]; return vnlVector; } } diff --git a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h index 02ab223a9f..8708ce140c 100644 --- a/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h +++ b/Modules/DiffusionImaging/FiberTracking/Algorithms/itkTractsToDWIImageFilter.h @@ -1,124 +1,130 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __itkTractsToDWIImageFilter_h__ #define __itkTractsToDWIImageFilter_h__ // MITK #include #include #include #include #include #include // ITK #include #include #include #include #include +#include + typedef itk::VectorImage< short, 3 > DWIImageType; namespace itk { /** * \brief Generates artificial diffusion weighted image volume from the input fiberbundle using a generic multicompartment model. */ class TractsToDWIImageFilter : public ImageSource< DWIImageType > { public: typedef TractsToDWIImageFilter Self; typedef ImageSource< DWIImageType > Superclass; typedef SmartPointer< Self > Pointer; typedef SmartPointer< const Self > ConstPointer; typedef itk::Image ItkDoubleImgType; typedef itk::Image ItkFloatImgType; typedef itk::Image ItkUcharImgType; typedef mitk::FiberBundleX::Pointer FiberBundleType; typedef itk::VectorImage< double, 3 > DoubleDwiType; typedef std::vector< mitk::KspaceArtifact* > KspaceArtifactList; typedef std::vector< mitk::DiffusionSignalModel* > DiffusionModelList; typedef itk::Matrix MatrixType; typedef mitk::DiffusionNoiseModel NoiseModelType; typedef itk::Image< double, 2 > SliceType; typedef itk::FFTRealToComplexConjugateImageFilter< double, 2 >::OutputImageType ComplexSliceType; itkNewMacro(Self) itkTypeMacro( TractsToDWIImageFilter, ImageToImageFilter ) // input + itkSetMacro( SignalScale, double ) + itkSetMacro( FiberRadius, double ) itkSetMacro( InterpolationShrink, double ) ///< large values shrink (towards nearest neighbour interpolation), small values strech interpolation function (towards linear interpolation) itkSetMacro( VolumeAccuracy, unsigned int ) ///< determines fiber sampling density and thereby the accuracy of the fiber volume fraction itkSetMacro( FiberBundle, FiberBundleType ) ///< input fiber bundle itkSetMacro( Spacing, mitk::Vector3D ) ///< output image spacing itkSetMacro( Origin, mitk::Point3D ) ///< output image origin itkSetMacro( DirectionMatrix, MatrixType ) ///< output image rotation itkSetMacro( EnforcePureFiberVoxels, bool ) ///< treat all voxels containing at least one fiber as fiber-only (actually disable non-fiber compartments for this voxel). itkSetMacro( ImageRegion, ImageRegion<3> ) ///< output image size itkSetMacro( NumberOfRepetitions, unsigned int ) ///< number of acquisition repetitions to reduce noise (default is no additional repetition) itkSetMacro( TissueMask, ItkUcharImgType::Pointer ) ///< voxels outside of this binary mask contain only noise (are treated as air) itkGetMacro( KspaceImage, ItkDoubleImgType::Pointer ) void SetNoiseModel(NoiseModelType* noiseModel){ m_NoiseModel = noiseModel; } ///< generates the noise added to the image values void SetFiberModels(DiffusionModelList modelList){ m_FiberModels = modelList; } ///< generate signal of fiber compartments void SetNonFiberModels(DiffusionModelList modelList){ m_NonFiberModels = modelList; } ///< generate signal of non-fiber compartments void SetKspaceArtifacts(KspaceArtifactList artifactList){ m_KspaceArtifacts = artifactList; } void GenerateData(); protected: TractsToDWIImageFilter(); virtual ~TractsToDWIImageFilter(); itk::Point GetItkPoint(double point[3]); itk::Vector GetItkVector(double point[3]); vnl_vector_fixed GetVnlVector(double point[3]); vnl_vector_fixed GetVnlVector(Vector< float, 3 >& vector); /** Transform generated image compartment by compartment, channel by channel and slice by slice using FFT and add k-space artifacts. */ std::vector< DoubleDwiType::Pointer > AddKspaceArtifacts(std::vector< DoubleDwiType::Pointer >& images); /** Rearrange FFT output to shift low frequencies to the iamge center (correct itk). */ TractsToDWIImageFilter::ComplexSliceType::Pointer RearrangeSlice(ComplexSliceType::Pointer slice); mitk::Vector3D m_Spacing; ///< output image spacing mitk::Vector3D m_UpsampledSpacing; mitk::Point3D m_Origin; ///< output image origin MatrixType m_DirectionMatrix; ///< output image rotation ImageRegion<3> m_ImageRegion; ///< output image size ImageRegion<3> m_UpsampledImageRegion; ItkUcharImgType::Pointer m_TissueMask; ///< voxels outside of this binary mask contain only noise (are treated as air) FiberBundleType m_FiberBundle; ///< input fiber bundle DiffusionModelList m_FiberModels; ///< generate signal of fiber compartments DiffusionModelList m_NonFiberModels; ///< generate signal of non-fiber compartments KspaceArtifactList m_KspaceArtifacts; NoiseModelType* m_NoiseModel; ///< generates the noise added to the image values bool m_CircleDummy; unsigned int m_VolumeAccuracy; ItkDoubleImgType::Pointer m_KspaceImage; unsigned int m_Upsampling; unsigned int m_NumberOfRepetitions; bool m_EnforcePureFiberVoxels; double m_InterpolationShrink; + double m_FiberRadius; + double m_SignalScale; }; } #include "itkTractsToDWIImageFilter.cpp" #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper2D.cpp b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper2D.cpp index ce6bb4268c..02046959d5 100644 --- a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper2D.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper2D.cpp @@ -1,336 +1,288 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /* * mitkFiberBundleMapper2D.cpp * mitk-all * * Created by HAL9000 on 1/17/11. * Copyright 2011 __MyCompanyName__. All rights reserved. * */ #include "mitkFiberBundleXMapper2D.h" #include #include #include #include #include //#include //#include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include mitk::FiberBundleXMapper2D::FiberBundleXMapper2D() { m_lut = vtkLookupTable::New(); m_lut->Build(); } mitk::FiberBundleXMapper2D::~FiberBundleXMapper2D() { } mitk::FiberBundleX* mitk::FiberBundleXMapper2D::GetInput() { - return dynamic_cast< mitk::FiberBundleX * > ( GetData() ); + return dynamic_cast< mitk::FiberBundleX * > ( GetDataNode()->GetData() ); } void mitk::FiberBundleXMapper2D::Update(mitk::BaseRenderer * renderer) { - if ( !this->IsVisible( renderer ) ) - { - return; - } + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible ) return; + MITK_DEBUG << "MapperFBX 2D update: "; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); //check if updates occured in the node or on the display FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); const DataNode *node = this->GetDataNode(); if ( (localStorage->m_LastUpdateTime < node->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { // MITK_INFO << "UPDATE NEEDED FOR _ " << renderer->GetName(); this->GenerateDataForRenderer( renderer ); } if ((localStorage->m_LastUpdateTime < renderer->GetDisplayGeometry()->GetMTime()) ) //was the display geometry modified? e.g. zooming, panning) { this->UpdateShaderParameter(renderer); } } void mitk::FiberBundleXMapper2D::UpdateShaderParameter(mitk::BaseRenderer * renderer) { FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //get information about current position of views mitk::SliceNavigationController::Pointer sliceContr = renderer->GetSliceNavigationController(); mitk::PlaneGeometry::ConstPointer planeGeo = sliceContr->GetCurrentPlaneGeometry(); //generate according cutting planes based on the view position float sliceN[3], planeOrigin[3]; // since shader uses camera coordinates, transform origin and normal from worldcoordinates to cameracoordinates planeOrigin[0] = (float) planeGeo->GetOrigin()[0]; planeOrigin[1] = (float) planeGeo->GetOrigin()[1]; planeOrigin[2] = (float) planeGeo->GetOrigin()[2]; sliceN[0] = planeGeo->GetNormal()[0]; sliceN[1] = planeGeo->GetNormal()[1]; sliceN[2] = planeGeo->GetNormal()[2]; float tmp1 = planeOrigin[0] * sliceN[0]; float tmp2 = planeOrigin[1] * sliceN[1]; float tmp3 = planeOrigin[2] * sliceN[2]; float d1 = tmp1 + tmp2 + tmp3; //attention, correct normalvector float plane1[4]; plane1[0] = sliceN[0]; plane1[1] = sliceN[1]; plane1[2] = sliceN[2]; plane1[3] = d1; float thickness = 2.0; if(!this->GetDataNode()->GetPropertyValue("Fiber2DSliceThickness",thickness)) MITK_INFO << "FIBER2D SLICE THICKNESS PROPERTY ERROR"; bool fiberfading = false; if(!this->GetDataNode()->GetPropertyValue("Fiber2DfadeEFX",fiberfading)) MITK_INFO << "FIBER2D SLICE FADE EFX PROPERTY ERROR"; int fiberfading_i = 1; if (!fiberfading) fiberfading_i = 0; // set Opacity float fiberOpacity; this->GetDataNode()->GetOpacity(fiberOpacity, NULL); localStorage->m_PointActor->GetProperty()->AddShaderVariable("slicingPlane",4, plane1); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberThickness",1, &thickness); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberFadingON",1, &fiberfading_i); localStorage->m_PointActor->GetProperty()->AddShaderVariable("fiberOpacity", 1, &fiberOpacity); } // ALL RAW DATA FOR VISUALIZATION IS GENERATED HERE. // vtkActors and Mappers are feeded here void mitk::FiberBundleXMapper2D::GenerateDataForRenderer(mitk::BaseRenderer *renderer) { //the handler of local storage gets feeded in this method with requested data for related renderwindow FBXLocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); //this procedure is depricated, //not needed after initializaton anymore mitk::DataNode* node = this->GetDataNode(); if ( node == NULL ) { MITK_INFO << "check DATANODE: ....[Fail] "; return; } /////////////////////////////////// ///THIS GET INPUT mitk::FiberBundleX* fbx = this->GetInput(); localStorage->m_PointMapper->ScalarVisibilityOn(); localStorage->m_PointMapper->SetScalarModeToUsePointFieldData(); localStorage->m_PointMapper->SetLookupTable(m_lut); //apply the properties after the slice was set localStorage->m_PointActor->GetProperty()->SetOpacity(0.999); // set color if (fbx->GetCurrentColorCoding() != NULL){ // localStorage->m_PointMapper->SelectColorArray(""); localStorage->m_PointMapper->SelectColorArray(fbx->GetCurrentColorCoding()); MITK_DEBUG << "MapperFBX 2D: " << fbx->GetCurrentColorCoding(); if(fbx->GetCurrentColorCoding() == fbx->COLORCODING_CUSTOM){ float temprgb[3]; this->GetDataNode()->GetColor( temprgb, NULL ); double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] }; localStorage->m_PointActor->GetProperty()->SetColor(trgb); } } localStorage->m_PointMapper->SetInput(fbx->GetFiberPolyData()); localStorage->m_PointActor->SetMapper(localStorage->m_PointMapper); localStorage->m_PointActor->GetProperty()->ShadingOn(); // Applying shading properties { mitk::ShaderRepository::GetGlobalShaderRepository()->ApplyProperties(this->GetDataNode(),localStorage->m_PointActor,renderer, localStorage->m_LastUpdateTime); } this->UpdateShaderParameter(renderer); // We have been modified => save this for next Update() localStorage->m_LastUpdateTime.Modified(); } vtkProp* mitk::FiberBundleXMapper2D::GetVtkProp(mitk::BaseRenderer *renderer) { //MITK_INFO << "FiberBundleMapper2D GetVtkProp(renderer)"; this->Update(renderer); return m_LSH.GetLocalStorage(renderer)->m_PointActor; } void mitk::FiberBundleXMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { //add shader to datano //####### load shader from file ######### QString applicationDir = QCoreApplication::applicationDirPath(); if (applicationDir.endsWith("bin")) applicationDir.append("/"); else if (applicationDir.endsWith("MacOS")) { //on osx, check if path for installer or MITK development is needed applicationDir.append("/"); QFile f( applicationDir+"FiberTrackingLUTBaryCoords.bin" ); if( !f.exists() ) // if file does not exist, then look in MITK development build directory applicationDir.append("../../../"); }else applicationDir.append("\\..\\"); mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch( applicationDir.toStdString().c_str(), false ); mitk::ShaderRepository::Pointer shaderRepository = mitk::ShaderRepository::GetGlobalShaderRepository(); shaderRepository->LoadShader(mitk::StandardFileLocations::GetInstance()->FindFile("mitkShaderFiberClipping.xml")); //#################################################################### node->SetProperty("shader",mitk::ShaderProperty::New("mitkShaderFiberClipping")); mitk::ShaderRepository::GetGlobalShaderRepository()->AddDefaultProperties(node,renderer,overwrite); //add other parameters to propertylist node->AddProperty( "Fiber2DSliceThickness", mitk::FloatProperty::New(2.0f), renderer, overwrite ); node->AddProperty( "Fiber2DfadeEFX", mitk::BoolProperty::New(true), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } - - - -// following methods are essential, they actually call the GetVtkProp() method -// which returns the desired actors -void mitk::FiberBundleXMapper2D::MitkRenderOverlay(BaseRenderer* renderer) -{ - // MITK_INFO << "FiberBundleMapper2D MitkRenderOVerlay(renderer)"; - if ( this->IsVisible(renderer)==false ) - return; - - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); - } -} - -void mitk::FiberBundleXMapper2D::MitkRenderOpaqueGeometry(BaseRenderer* renderer) -{ - // MITK_INFO << "FiberBundleMapper2D MitkRenderOpaqueGeometry(renderer)"; - if ( this->IsVisible( renderer )==false ) - return; - - if ( this->GetVtkProp(renderer)->GetVisibility() ) - this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); -} -void mitk::FiberBundleXMapper2D::MitkRenderTranslucentGeometry(BaseRenderer* renderer) -{ - // MITK_INFO << "FiberBundleMapper2D MitkRenderTranslucentGeometry(renderer)"; - if ( this->IsVisible(renderer)==false ) - return; - - //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer??? - if ( this->GetVtkProp(renderer)->GetVisibility() ) - this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); - -} -void mitk::FiberBundleXMapper2D::MitkRenderVolumetricGeometry(BaseRenderer* renderer) -{ - // MITK_INFO << "FiberBundleMapper2D MitkRenderVolumentricGeometry(renderer)"; - if(IsVisible(renderer)==false) - return; - - //TODO is it possible to have a visible BaseRenderer AND an invisible VtkRenderer??? - if ( GetVtkProp(renderer)->GetVisibility() ) - this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); - -} - mitk::FiberBundleXMapper2D::FBXLocalStorage::FBXLocalStorage() { m_PointActor = vtkSmartPointer::New(); m_PointMapper = vtkSmartPointer::New(); } diff --git a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper2D.h b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper2D.h index 40a4110f13..6381cb381d 100644 --- a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper2D.h +++ b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper2D.h @@ -1,111 +1,107 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef FIBERBUNDLEXMAPPER2D_H_HEADER_INCLUDED #define FIBERBUNDLEXMAPPER2D_H_HEADER_INCLUDED //MITK Rendering #include #include //#include "FiberTrackingExports.h" -#include +#include #include #include class vtkActor; //class vtkPropAssembly; //lets see if we need it class mitkBaseRenderer; class vtkPolyDataMapper; class vtkCutter; class vtkPlane; class vtkPolyData; namespace mitk { - class FiberBundleXMapper2D : public VtkMapper2D + class FiberBundleXMapper2D : public VtkMapper { public: - mitkClassMacro(FiberBundleXMapper2D, VtkMapper2D); + mitkClassMacro(FiberBundleXMapper2D, VtkMapper); itkNewMacro(Self); mitk::FiberBundleX* GetInput(); /** \brief Checks whether this mapper needs to update itself and generate * data. */ virtual void Update(mitk::BaseRenderer * renderer); static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); //### methods of MITK-VTK rendering pipeline virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); - virtual void MitkRenderOverlay(BaseRenderer* renderer); - virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer); - virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer); - virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer); //### end of methods of MITK-VTK rendering pipeline class FBXLocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Point Actor of a 2D render window. */ vtkSmartPointer m_PointActor; /** \brief Point Mapper of a 2D render window. */ vtkSmartPointer m_PointMapper; vtkSmartPointer m_SlicingPlane; //needed later when optimized 2D mapper vtkSmartPointer m_SlicedResult; //might be depricated in optimized 2D mapper /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief Constructor of the local storage. Do as much actions as possible in here to avoid double executions. */ FBXLocalStorage(); //if u copy&paste from this 2Dmapper, be aware that the implementation of this constructor is in the cpp file ~FBXLocalStorage() { } }; /** \brief This member holds all three LocalStorages for the three 2D render windows. */ mitk::Mapper::LocalStorageHandler m_LSH; protected: FiberBundleXMapper2D(); virtual ~FiberBundleXMapper2D(); /** Does the actual resampling, without rendering. */ virtual void GenerateDataForRenderer(mitk::BaseRenderer*); void UpdateShaderParameter(mitk::BaseRenderer*); private: vtkSmartPointer m_lut; }; }//end namespace #endif diff --git a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper3D.cpp b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper3D.cpp index 51fa92e13c..75c540a01e 100644 --- a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper3D.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper3D.cpp @@ -1,200 +1,202 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFiberBundleXMapper3D.h" #include //#include //#include #include #include #include #include //not essential for mapper #include mitk::FiberBundleXMapper3D::FiberBundleXMapper3D() { m_lut = vtkLookupTable::New(); m_lut->Build(); } mitk::FiberBundleXMapper3D::~FiberBundleXMapper3D() { } const mitk::FiberBundleX* mitk::FiberBundleXMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } /* This method is called once the mapper gets new input, for UI rotation or changes in colorcoding this method is NOT called */ void mitk::FiberBundleXMapper3D::GenerateData(mitk::BaseRenderer *renderer) { //MITK_INFO << "GENERATE DATA FOR FBX :)"; //=====timer measurement==== QTime myTimer; myTimer.start(); //========================== - mitk::FiberBundleX* FBX = dynamic_cast (this->GetData()); + mitk::FiberBundleX* FBX = dynamic_cast (GetDataNode()->GetData()); if (FBX == NULL) return; vtkSmartPointer FiberData = FBX->GetFiberPolyData(); if (FiberData == NULL) return; FBXLocalStorage3D *localStorage = m_LSH.GetLocalStorage(renderer); localStorage->m_FiberMapper->SetInput(FiberData); if ( FiberData->GetPointData()->GetNumberOfArrays() > 0 ) localStorage->m_FiberMapper->SelectColorArray( FBX->GetCurrentColorCoding() ); localStorage->m_FiberMapper->ScalarVisibilityOn(); localStorage->m_FiberMapper->SetScalarModeToUsePointFieldData(); localStorage->m_FiberActor->SetMapper(localStorage->m_FiberMapper); localStorage->m_FiberMapper->SetLookupTable(m_lut); // set Opacity float tmpopa; this->GetDataNode()->GetOpacity(tmpopa, NULL); localStorage->m_FiberActor->GetProperty()->SetOpacity((double) tmpopa); // set color if (FBX->GetCurrentColorCoding() != NULL){ // localStorage->m_FiberMapper->SelectColorArray(""); localStorage->m_FiberMapper->SelectColorArray(FBX->GetCurrentColorCoding()); MITK_DEBUG << "MapperFBX: " << FBX->GetCurrentColorCoding(); if(FBX->GetCurrentColorCoding() == FBX->COLORCODING_CUSTOM) { float temprgb[3]; this->GetDataNode()->GetColor( temprgb, NULL ); double trgb[3] = { (double) temprgb[0], (double) temprgb[1], (double) temprgb[2] }; localStorage->m_FiberActor->GetProperty()->SetColor(trgb); } } localStorage->m_FiberAssembly->AddPart(localStorage->m_FiberActor); localStorage->m_LastUpdateTime.Modified(); //since this method is called after generating all necessary data for fiber visualization, all modifications are represented so far. } void mitk::FiberBundleXMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { - if ( !this->IsVisible( renderer ) ) - return; + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible ) return; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper this->CalculateTimeStep( renderer ); //check if updates occured in the node or on the display FBXLocalStorage3D *localStorage = m_LSH.GetLocalStorage(renderer); const DataNode *node = this->GetDataNode(); if ( (localStorage->m_LastUpdateTime < node->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { MITK_DEBUG << "UPDATE NEEDED FOR _ " << renderer->GetName(); this->GenerateData(renderer); } } void mitk::FiberBundleXMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { // MITK_INFO << "FiberBundleXxXXMapper3D()SetDefaultProperties"; //MITK_INFO << "FiberBundleMapperX3D SetDefault Properties(...)"; // node->AddProperty( "DisplayChannel", mitk::IntProperty::New( true ), renderer, overwrite ); node->AddProperty( "LineWidth", mitk::IntProperty::New( true ), renderer, overwrite ); node->AddProperty( "opacity", mitk::FloatProperty::New( 1.0 ), renderer, overwrite); // node->AddProperty( "VertexOpacity_1", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "Set_FA_VertexAlpha", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "pointSize", mitk::FloatProperty::New(0.5), renderer, overwrite); // node->AddProperty( "setShading", mitk::IntProperty::New(1), renderer, overwrite); // node->AddProperty( "Xmove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "Ymove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "Zmove", mitk::IntProperty::New( 0 ), renderer, overwrite); // node->AddProperty( "RepPoints", mitk::BoolProperty::New( false ), renderer, overwrite); // node->AddProperty( "TubeSides", mitk::IntProperty::New( 8 ), renderer, overwrite); // node->AddProperty( "TubeRadius", mitk::FloatProperty::New( 0.15 ), renderer, overwrite); // node->AddProperty( "TubeOpacity", mitk::FloatProperty::New( 1.0 ), renderer, overwrite); node->AddProperty( "pickable", mitk::BoolProperty::New( true ), renderer, overwrite); Superclass::SetDefaultProperties(node, renderer, overwrite); } vtkProp* mitk::FiberBundleXMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { //MITK_INFO << "FiberBundleXxXXMapper3D()GetVTKProp"; //this->GenerateData(); return m_LSH.GetLocalStorage(renderer)->m_FiberAssembly; } void mitk::FiberBundleXMapper3D::ApplyProperties(mitk::BaseRenderer* renderer) { } void mitk::FiberBundleXMapper3D::UpdateVtkObjects() { } void mitk::FiberBundleXMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) { } mitk::FiberBundleXMapper3D::FBXLocalStorage3D::FBXLocalStorage3D() { m_FiberActor = vtkSmartPointer::New(); m_FiberMapper = vtkSmartPointer::New(); m_FiberAssembly = vtkSmartPointer::New(); } diff --git a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper3D.h b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper3D.h index 6d238416cc..f4e73c98e4 100644 --- a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper3D.h +++ b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXMapper3D.h @@ -1,104 +1,104 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef FiberBundleXMapper3D_H_HEADER_INCLUDED #define FiberBundleXMapper3D_H_HEADER_INCLUDED //#include //?? necessary #include -#include +#include #include #include #include #include #include class vtkPropAssembly; namespace mitk { //##Documentation //## @brief Mapper for FiberBundleX //## @ingroup Mapper -class FiberTracking_EXPORT FiberBundleXMapper3D : public VtkMapper3D +class FiberTracking_EXPORT FiberBundleXMapper3D : public VtkMapper { public: - mitkClassMacro(FiberBundleXMapper3D, VtkMapper3D); + mitkClassMacro(FiberBundleXMapper3D, VtkMapper); itkNewMacro(Self); //========== essential implementation for 3D mapper ======== const FiberBundleX* GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); //looks like depricated.. should be replaced bz GetViewProp() static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); virtual void ApplyProperties(mitk::BaseRenderer* renderer); static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); //========================================================= virtual void GenerateData(mitk::BaseRenderer *renderer); class FBXLocalStorage3D : public mitk::Mapper::BaseLocalStorage { public: /** \brief Point Actor of a 3D render window. */ vtkSmartPointer m_FiberActor; /** \brief Point Mapper of a 3D render window. */ vtkSmartPointer m_FiberMapper; vtkSmartPointer m_FiberAssembly; /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief Constructor of the local storage. Do as much actions as possible in here to avoid double executions. */ FBXLocalStorage3D(); //if u copy&paste from this 2Dmapper, be aware that the implementation of this constructor is in the cpp file ~FBXLocalStorage3D() { } }; /** \brief This member holds all three LocalStorages for the 3D render window(s). */ mitk::Mapper::LocalStorageHandler m_LSH; protected: FiberBundleXMapper3D(); virtual ~FiberBundleXMapper3D(); void UpdateVtkObjects(); //?? private: vtkSmartPointer m_lut; }; } // end namespace mitk #endif /* FiberBundleXMapper3D_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp index b26341abea..311a5f6733 100644 --- a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp +++ b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.cpp @@ -1,213 +1,205 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkFiberBundleXThreadMonitorMapper3D.h" #include #include //#include #include mitk::FiberBundleXThreadMonitorMapper3D::FiberBundleXThreadMonitorMapper3D() : m_FiberMonitorMapper(vtkSmartPointer::New()) , m_TextActorClose(vtkSmartPointer::New()) , m_TextActorOpen(vtkSmartPointer::New()) , m_TextActorHeading(vtkSmartPointer::New()) , m_TextActorMask(vtkSmartPointer::New()) , m_TextActorStatus(vtkSmartPointer::New()) , m_TextActorStarted(vtkSmartPointer::New()) , m_TextActorFinished(vtkSmartPointer::New()) , m_TextActorTerminated(vtkSmartPointer::New()) , m_FiberAssembly(vtkPropAssembly::New()) , m_lastModifiedMonitorNodeTime(-1) { m_FiberAssembly->AddPart(m_TextActorClose); m_FiberAssembly->AddPart(m_TextActorOpen); m_FiberAssembly->AddPart(m_TextActorHeading); m_FiberAssembly->AddPart(m_TextActorMask); m_FiberAssembly->AddPart(m_TextActorStatus); m_FiberAssembly->AddPart(m_TextActorStarted); m_FiberAssembly->AddPart(m_TextActorFinished); m_FiberAssembly->AddPart(m_TextActorTerminated); } mitk::FiberBundleXThreadMonitorMapper3D::~FiberBundleXThreadMonitorMapper3D() { m_FiberAssembly->Delete(); } const mitk::FiberBundleXThreadMonitor* mitk::FiberBundleXThreadMonitorMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } /* This method is called once the mapper gets new input, for UI rotation or changes in colorcoding this method is NOT called */ -void mitk::FiberBundleXThreadMonitorMapper3D::GenerateData() +void mitk::FiberBundleXThreadMonitorMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { -// MITK_INFO << m_LastUpdateTime; - FiberBundleXThreadMonitor* monitor = dynamic_cast ( GetData() ); + + // MITK_INFO << m_LastUpdateTime; + FiberBundleXThreadMonitor* monitor = dynamic_cast ( GetDataNode()->GetData() ); // m_TextActor->SetInput( monitor->getTextL1().toStdString().c_str() ); m_TextActorClose->SetInput( monitor->getBracketClose().toStdString().c_str() ); vtkTextProperty* tpropClose = m_TextActorClose->GetTextProperty(); //tprop->SetFontFamilyToArial (); //tprop->SetLineSpacing(1.0); tpropClose->SetFontSize(16); tpropClose->SetColor(0.85,0.8,0.8); m_TextActorClose->SetDisplayPosition( monitor->getBracketClosePosition()[0], monitor->getBracketClosePosition()[1] ); //m_TextActorClose->Modified(); m_TextActorOpen->SetInput( monitor->getBracketOpen().toStdString().c_str() ); vtkTextProperty* tpropOpen = m_TextActorOpen->GetTextProperty(); //tprop->SetFontFamilyToArial (); //tprop->SetLineSpacing(1.0); tpropOpen->SetFontSize(16); tpropOpen->SetColor(0.85,0.8,0.8); m_TextActorOpen->SetDisplayPosition( monitor->getBracketOpenPosition()[0], monitor->getBracketOpenPosition()[1] ); //m_TextActorOpen->Modified(); - m_TextActorHeading->SetInput( monitor->getHeading().toStdString().c_str() ); vtkTextProperty* tpropHeading = m_TextActorHeading->GetTextProperty(); tpropHeading->SetFontSize(12); tpropHeading->SetOpacity( monitor->getHeadingOpacity() * 0.1 ); tpropHeading->SetColor(0.85,0.8,0.8); m_TextActorHeading->SetDisplayPosition( monitor->getHeadingPosition()[0], monitor->getHeadingPosition()[1] ); //m_TextActorHeading->Modified(); m_TextActorMask->SetInput( monitor->getMask().toStdString().c_str() ); vtkTextProperty* tpropMask = m_TextActorMask->GetTextProperty(); tpropMask->SetFontSize(12); tpropMask->SetOpacity( monitor->getMaskOpacity() * 0.1 ); tpropMask->SetColor(1.0,1.0,1.0); m_TextActorMask->SetDisplayPosition( monitor->getMaskPosition()[0], monitor->getMaskPosition()[1] ); //m_TextActorHeading->Modified(); m_TextActorStatus->SetInput(monitor->getStatus().toStdString().c_str()); vtkTextProperty* tpropStatus = m_TextActorStatus->GetTextProperty(); tpropStatus->SetFontSize(10); tpropStatus->SetOpacity( monitor->getStatusOpacity() * 0.1 ); tpropStatus->SetColor(0.85,0.8,0.8); m_TextActorStatus->SetDisplayPosition( monitor->getStatusPosition()[0], monitor->getStatusPosition()[1] ); //m_TextActorStatus->Modified(); m_TextActorStarted->SetInput(QString::number(monitor->getStarted()).toStdString().c_str()); vtkTextProperty* tpropStarted = m_TextActorStarted->GetTextProperty(); tpropStarted->SetFontSize(12); tpropStarted->SetOpacity( monitor->getStartedOpacity() * 0.1 ); tpropStarted->SetColor(0.0,1.0,0.0); m_TextActorStarted->SetDisplayPosition( monitor->getStartedPosition()[0], monitor->getStartedPosition()[1] ); //m_TextActorStarted->Modified(); m_TextActorFinished->SetInput(QString::number(monitor->getFinished()).toStdString().c_str()); vtkTextProperty* tpropFinished = m_TextActorFinished->GetTextProperty(); tpropFinished->SetFontSize(12); tpropFinished->SetOpacity( monitor->getFinishedOpacity() * 0.1 ); tpropFinished->SetColor(1.0,1.0,1.0); m_TextActorFinished->SetDisplayPosition( monitor->getFinishedPosition()[0], monitor->getFinishedPosition()[1] ); //m_TextActorFinished->Modified(); m_TextActorTerminated->SetInput(QString::number(monitor->getTerminated()).toStdString().c_str()); vtkTextProperty* tpropTerminated = m_TextActorTerminated->GetTextProperty(); tpropTerminated->SetFontSize(12); tpropTerminated->SetOpacity( monitor->getTerminatedOpacity() * 0.1 ); tpropTerminated->SetColor(1.0,1.0,1.0); m_TextActorTerminated->SetDisplayPosition( monitor->getTerminatedPosition()[0], monitor->getTerminatedPosition()[1] ); //m_TextActorTerminated->Modified(); + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); -} - - - -void mitk::FiberBundleXThreadMonitorMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) -{ - if ( !this->IsVisible( renderer ) ) - { - return; - } + if ( !visible ) return; // Calculate time step of the input data for the specified renderer (integer value) // this method is implemented in mitkMapper // this->CalculateTimeStep( renderer ); const DataNode *node = this->GetDataNode(); if (m_lastModifiedMonitorNodeTime < node->GetMTime()) { - this->GenerateData(); m_lastModifiedMonitorNodeTime = node->GetMTime(); } } void mitk::FiberBundleXThreadMonitorMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { // MITK_INFO << "FiberBundleXxXXMapper3D()SetDefaultProperties"; Superclass::SetDefaultProperties(node, renderer, overwrite); } vtkProp* mitk::FiberBundleXThreadMonitorMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { //MITK_INFO << "FiberBundleXxXXMapper3D()GetVTKProp"; //this->GenerateData(); return m_FiberAssembly; } void mitk::FiberBundleXThreadMonitorMapper3D::ApplyProperties(mitk::BaseRenderer* renderer) { // MITK_INFO << "FiberBundleXXXXMapper3D ApplyProperties(renderer)"; } void mitk::FiberBundleXThreadMonitorMapper3D::UpdateVtkObjects() { // MITK_INFO << "FiberBundleXxxXMapper3D UpdateVtkObjects()"; } void mitk::FiberBundleXThreadMonitorMapper3D::SetVtkMapperImmediateModeRendering(vtkMapper *) { } diff --git a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.h b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.h index dbff4caf6c..45c259fd93 100644 --- a/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.h +++ b/Modules/DiffusionImaging/FiberTracking/Rendering/mitkFiberBundleXThreadMonitorMapper3D.h @@ -1,90 +1,89 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef FiberBundleXThreadMonitorMapper3D_H_HEADER_INCLUDED #define FiberBundleXThreadMonitorMapper3D_H_HEADER_INCLUDED //#include //?? necessary #include -#include +#include #include #include #include #include class vtkPropAssembly; namespace mitk { //##Documentation //## @brief Mapper for FiberBundleX //## @ingroup Mapper - class FiberTracking_EXPORT FiberBundleXThreadMonitorMapper3D : public VtkMapper3D + class FiberTracking_EXPORT FiberBundleXThreadMonitorMapper3D : public VtkMapper { public: - mitkClassMacro(FiberBundleXThreadMonitorMapper3D, VtkMapper3D); + mitkClassMacro(FiberBundleXThreadMonitorMapper3D, VtkMapper); itkNewMacro(Self); //========== essential implementation for 3D mapper ======== const FiberBundleXThreadMonitor* GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); //looks like depricated.. should be replaced bz GetViewProp() static void SetDefaultProperties(DataNode* node, BaseRenderer* renderer = NULL, bool overwrite = false ); virtual void ApplyProperties(mitk::BaseRenderer* renderer); static void SetVtkMapperImmediateModeRendering(vtkMapper *mapper); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); - virtual void GenerateData(); //========================================================= protected: FiberBundleXThreadMonitorMapper3D(); virtual ~FiberBundleXThreadMonitorMapper3D(); void UpdateVtkObjects(); //?? vtkSmartPointer m_FiberMonitorMapper; vtkSmartPointer m_TextActorClose; vtkSmartPointer m_TextActorOpen; vtkSmartPointer m_TextActorHeading; vtkSmartPointer m_TextActorMask; vtkSmartPointer m_TextActorStatus; vtkSmartPointer m_TextActorStarted; vtkSmartPointer m_TextActorFinished; vtkSmartPointer m_TextActorTerminated; vtkPropAssembly* m_FiberAssembly; private: double m_lastModifiedMonitorNodeTime; }; } // end namespace mitk #endif /* FiberBundleXMapper3D_H_HEADER_INCLUDED */ diff --git a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionSignalModel.h b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionSignalModel.h index e2f9a7fb3d..c00350e76f 100644 --- a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionSignalModel.h +++ b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkDiffusionSignalModel.h @@ -1,81 +1,80 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_DiffusionSignalModel_H #define _MITK_DiffusionSignalModel_H #include #include #include #include namespace mitk { /** * \brief Abstract class for diffusion signal models * */ template< class ScalarType > class DiffusionSignalModel { public: - DiffusionSignalModel() : m_SignalScale(200){} + DiffusionSignalModel() + : m_T2(100) + {} ~DiffusionSignalModel(){} typedef itk::VariableLengthVector< ScalarType > PixelType; typedef itk::Vector GradientType; typedef std::vector GradientListType; /** Realizes actual signal generation. Has to be implemented in subclass. **/ virtual PixelType SimulateMeasurement() = 0; void SetFiberDirection(GradientType fiberDirection){ m_FiberDirection = fiberDirection; } void SetGradientList(GradientListType gradientList) { m_GradientList = gradientList; } - void SetSignalScale(ScalarType signalScale) { m_SignalScale = signalScale; } - void SetRelaxationT2(double T2) { m_RelaxationT2 = T2; } + void SetT2(double T2) { m_T2 = T2; } - double GetRelaxationT2() { return m_RelaxationT2; } - ScalarType GetSignalScale() { return m_SignalScale; } + double GetT2() { return m_T2; } int GetNumGradients(){ return m_GradientList.size(); } std::vector< int > GetBaselineIndices() { std::vector< int > result; for( unsigned int i=0; im_GradientList.size(); i++) if (m_GradientList.at(i).GetNorm()<0.0001) result.push_back(i); return result; } int GetFirstBaselineIndex() { for( unsigned int i=0; im_GradientList.size(); i++) if (m_GradientList.at(i).GetNorm()<0.0001) return i; return -1; } protected: GradientType m_FiberDirection; ///< Needed to generate anisotropc signal to determin direction of anisotropy GradientListType m_GradientList; ///< Diffusion gradient direction container - ScalarType m_SignalScale; ///< Scaling factor for signal value - double m_RelaxationT2; ///< Tissue specific relaxation time (used for artificial artifacts) + double m_T2; ///< Tissue specific relaxation time }; } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkKspaceArtifact.h b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkKspaceArtifact.h index eb204990d8..5c76a38364 100644 --- a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkKspaceArtifact.h +++ b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkKspaceArtifact.h @@ -1,55 +1,66 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_KspaceArtifact_H #define _MITK_KspaceArtifact_H #include #include #include namespace mitk { /** * \brief Abstract class for diffusion noise models * */ template< class ScalarType > class KspaceArtifact { public: - KspaceArtifact(){ m_T2=90; } + KspaceArtifact() + : m_T2(2000) + , m_TE(20) + , m_T2star(50) + , m_LineReadoutTime(1) + { + } ~KspaceArtifact(){} typedef typename itk::FFTRealToComplexConjugateImageFilter< ScalarType, 2 >::OutputImageType ComplexSliceType; /** Adds artifact according to model to the input slice. Has to be implemented in subclass. **/ virtual typename ComplexSliceType::Pointer AddArtifact(typename ComplexSliceType::Pointer slice) = 0; - void SetRelaxationT2(unsigned int T2){ m_T2=T2; } + void SetTline(unsigned int LineReadoutTime){ m_LineReadoutTime=LineReadoutTime; } + void SetT2(unsigned int T2){ m_T2=T2; } + void SetTE(unsigned int TE){ m_TE=TE; } + void SetT2star(unsigned int T2star){ m_T2star=T2star; } protected: - unsigned int m_T2; - + unsigned int m_T2star; + unsigned int m_T2; + unsigned int m_TE; + double m_LineReadoutTime; }; } #endif diff --git a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkT2SmearingArtifact.cpp b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkT2SmearingArtifact.cpp index 6dc8a894b5..3c6d08c671 100644 --- a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkT2SmearingArtifact.cpp +++ b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkT2SmearingArtifact.cpp @@ -1,45 +1,53 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ template< class ScalarType > T2SmearingArtifact< ScalarType >::T2SmearingArtifact() - : m_ReadoutPulseLength(1) { } template< class ScalarType > T2SmearingArtifact< ScalarType >::~T2SmearingArtifact() { } template< class ScalarType > typename T2SmearingArtifact< ScalarType >::ComplexSliceType::Pointer T2SmearingArtifact< ScalarType >::AddArtifact(typename ComplexSliceType::Pointer slice) { itk::ImageRegion<2> region = slice->GetLargestPossibleRegion(); + + double dt = (double)this->m_LineReadoutTime/region.GetSize(0); + + double from90 = (double)this->m_TE - this->m_LineReadoutTime*(double)region.GetSize(1)/2; + double fromMaxEcho = - this->m_LineReadoutTime*(double)region.GetSize(1)/2; + for (int y=0; y pix = slice->GetPixel(idx); - double t = m_ReadoutPulseLength*(y+(double)x/region.GetSize(0)); - std::complex< double > newPix(pix.real()*exp(-t/this->m_T2), pix.imag()*exp(-t/this->m_T2)); + double fact = exp(-from90/this->m_T2 -fabs(fromMaxEcho)/this->m_T2star); + std::complex< double > newPix(fact*pix.real(), fact*pix.imag()); slice->SetPixel(idx, newPix); + + from90 += dt; + fromMaxEcho += dt; } return slice; } diff --git a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkT2SmearingArtifact.h b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkT2SmearingArtifact.h index 2348cd2bb9..71d05dcc29 100644 --- a/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkT2SmearingArtifact.h +++ b/Modules/DiffusionImaging/FiberTracking/SignalModels/mitkT2SmearingArtifact.h @@ -1,57 +1,53 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_T2SmearingArtifact_H #define _MITK_T2SmearingArtifact_H #include #include #include #include namespace mitk { /** * \brief Class to add gibbs ringing artifact to input complex slice * */ template< class ScalarType > class T2SmearingArtifact : public KspaceArtifact< ScalarType > { public: T2SmearingArtifact(); ~T2SmearingArtifact(); typedef typename KspaceArtifact< ScalarType >::ComplexSliceType ComplexSliceType; /** Attenuate signal according to given T2 time. **/ typename ComplexSliceType::Pointer AddArtifact(typename ComplexSliceType::Pointer slice); - void SetReadoutPulseLength(double t){ m_ReadoutPulseLength=t; } - protected: - unsigned int m_ReadoutPulseLength; - }; #include "mitkT2SmearingArtifact.cpp" } #endif diff --git a/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.cpp b/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.cpp index 1a2cf91fad..cde313ed90 100644 --- a/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.cpp +++ b/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.cpp @@ -1,437 +1,434 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkEnhancedPointSetVtkMapper3D.h" //#include #include #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkLookupTables.h" #include "mitkColorProperty.h" //#include "mitkVtkPropRenderer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include const mitk::PointSet* mitk::EnhancedPointSetVtkMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } mitk::EnhancedPointSetVtkMapper3D::EnhancedPointSetVtkMapper3D() { m_Contour = vtkActor::New(); m_ContourSource = vtkTubeFilter::New(); m_PropAssembly = vtkAssembly::New(); } vtkProp* mitk::EnhancedPointSetVtkMapper3D::GetVtkProp(mitk::BaseRenderer* /*renderer*/) { return m_PropAssembly; } mitk::EnhancedPointSetVtkMapper3D::~EnhancedPointSetVtkMapper3D() { m_Contour->Delete(); m_ContourSource->Delete(); m_PropAssembly->Delete(); // TODO: do cleanup correctly // Clean up all remaining actors and poly-data sources //std::for_each(m_PointActors.begin(), m_PointActors.end(), &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject); // std::for_each(m_SphereSources.begin(), m_SphereSources.end(), &mitk::EnhancedPointSetVtgkMapper3D::DeleteVtkObject); // std::for_each(m_CubeSources.begin(), m_CubeSources.end(), &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject); // std::for_each(m_ConeSources.begin(), m_ConeSources.end(), &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject); // std::for_each(m_CylinderSources.begin(), m_CylinderSources.end(), &mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject); // } void mitk::EnhancedPointSetVtkMapper3D::ReleaseGraphicsResources(vtkWindow * /*renWin*/) { // TODO: Do we have to call this for all actors?? //m_Actor->ReleaseGraphicsResources(renWin); } void mitk::EnhancedPointSetVtkMapper3D::UpdateVtkObjects() { // get and update the PointSet const mitk::PointSet* pointset = this->GetInput(); //pointset->Update(); int timestep = this->GetTimestep(); mitk::PointSet::DataType* itkPointSet = pointset->GetPointSet( timestep ); mitk::PointSet::PointsContainer* points = itkPointSet->GetPoints(); mitk::PointSet::PointDataContainer* pointData = itkPointSet->GetPointData(); assert(points->Size() == pointData->Size()); mitk::PointSet::PointsIterator pIt; mitk::PointSet::PointDataIterator pdIt; /* search removed points and delete the corresponding source/actor/mapper objects */ for (ActorMap::iterator it = m_PointActors.begin(); it != m_PointActors.end(); ) { PointIdentifier id = it->first; if (!points->IndexExists(id)) { this->RemoveEntryFromSourceMaps(id); m_PropAssembly->GetParts()->RemoveItem(it->second.first); // remove from prop assembly if (it->second.first != NULL) it->second.first->Delete(); // Delete actor, which deletes mapper too (reference count) ActorMap::iterator er = it; // save iterator for deleting ++it; // advance iterator to next object m_PointActors.erase(er); // erase element from map. This invalidates er, therefore we had to advance it before deletion. } else ++it; } /* iterate over each point in the pointset and create corresponding vtk objects */ for (pIt = points->Begin(), pdIt = pointData->Begin(); pIt != itkPointSet->GetPoints()->End(); ++pIt, ++pdIt) { PointIdentifier pointID = pIt->Index(); assert (pointID == pdIt->Index()); mitk::PointSet::PointType point = pIt->Value(); mitk::PointSet::PointDataType data = pdIt->Value(); ActorMap::iterator aIt = m_PointActors.find(pointID); // Does an actor exist for the point? /* Create/Update sources for the point */ vtkActor* a = NULL; bool newPoint = (aIt == m_PointActors.end()); // current point is new bool specChanged = (!newPoint && data.pointSpec != aIt->second.second); // point spec of current point has changed if (newPoint) // point did not exist before, we have to create vtk objects for it { // create actor and mapper for the new point a = vtkActor::New(); vtkPolyDataMapper* m = vtkPolyDataMapper::New(); a->SetMapper(m); m->UnRegister( NULL ); aIt = m_PointActors.insert(std::make_pair(pointID, std::make_pair(a, data.pointSpec))).first; // insert element and update actormap iterator to point to new element m_PropAssembly->AddPart(a); } else { a = aIt->second.first; if (specChanged) // point exists, but point spec has changed { this->RemoveEntryFromSourceMaps( pointID ); } } if ( newPoint || specChanged ) // new point OR existing point but point spec changed { vtkPolyDataAlgorithm* source = NULL; // works only in VTK 5+ switch (data.pointSpec) // add to new map { //TODO: look up representation in a representationlookuptable case PTSTART: //cube m_CubeSources[pointID] = vtkCubeSource::New(); source = m_CubeSources[pointID]; break; case PTCORNER: //cone m_ConeSources[pointID] = vtkConeSource::New(); source = m_ConeSources[pointID]; break; case PTEDGE: // cylinder m_CylinderSources[pointID] = vtkCylinderSource::New(); source = m_CylinderSources[pointID]; break; case PTUNDEFINED: // sphere case PTEND: default: m_SphereSources[pointID] = vtkSphereSource::New(); source = m_SphereSources[pointID]; break; } vtkPolyDataMapper* m = dynamic_cast(a->GetMapper()); assert(m != NULL); m->SetInput(source->GetOutput()); aIt->second.second = data.pointSpec; // update point spec in actormap } } // for each point } -void mitk::EnhancedPointSetVtkMapper3D::GenerateData() +void mitk::EnhancedPointSetVtkMapper3D::ApplyProperties( mitk::BaseRenderer * renderer ) { - this->UpdateVtkObjects(); -} + this->UpdateVtkObjects(); -void mitk::EnhancedPointSetVtkMapper3D::ApplyProperties( mitk::BaseRenderer * renderer ) -{ /* iterate over all points in pointset and apply properties to corresponding vtk objects */ // get and update the PointSet const mitk::PointSet* pointset = this->GetInput(); int timestep = this->GetTimestep(); mitk::PointSet::DataType* itkPointSet = pointset->GetPointSet( timestep ); mitk::PointSet::PointsContainer* points = itkPointSet->GetPoints(); mitk::PointSet::PointDataContainer* pointData = itkPointSet->GetPointData(); assert(points->Size() == pointData->Size()); mitk::PointSet::PointsIterator pIt; mitk::PointSet::PointDataIterator pdIt; mitk::DataNode* n = this->GetDataNode(); assert(n != NULL); for (pIt = points->Begin(), pdIt = pointData->Begin(); pIt != itkPointSet->GetPoints()->End(); ++pIt, ++pdIt) // for each point in the pointset { PointIdentifier pointID = pIt->Index(); assert (pointID == pdIt->Index()); mitk::PointSet::PointType point = pIt->Value(); mitk::PointSet::PointDataType data = pdIt->Value(); ActorMap::iterator aIt = m_PointActors.find(pointID); // Does an actor exist for the point? assert(aIt != m_PointActors.end()); // UpdateVtkObjects() must ensure that actor exists vtkActor* a = aIt->second.first; assert(a != NULL); SetVtkMapperImmediateModeRendering(a->GetMapper()); /* update properties */ // visibility bool pointVisibility = true; bool visValueFound = false; mitk::BaseProperty* visProp = n->GetProperty("visibility", renderer); mitk::BoolLookupTableProperty* visLTProp = dynamic_cast(visProp); if (visLTProp != NULL) { mitk::BoolLookupTable visLookupTable = visLTProp->GetValue(); //if (visLookupTable != NULL) //{ try { pointVisibility = visLookupTable.GetTableValue(pointID); visValueFound = true; } catch (...) { } //} } if (visValueFound == false) { pointVisibility = n->IsVisible(renderer, "show points"); // use BoolProperty instead } a->SetVisibility(pointVisibility); // opacity float opacity = 1.0; bool opValueFound = false; mitk::BaseProperty* opProp = n->GetProperty("opacity", renderer); mitk::FloatLookupTableProperty* opLTProp = dynamic_cast(opProp); if (opLTProp != NULL) { mitk::FloatLookupTable opLookupTable = opLTProp->GetValue(); //if (opLookupTable != NULL) //{ try { opacity = opLookupTable.GetTableValue(pointID); opValueFound = true; } catch (...) { } //} } if (opValueFound == false) { n->GetOpacity(opacity, renderer); } a->GetProperty()->SetOpacity(opacity); ////////////////////// continue here /////////////////// // pointsize & point position float pointSize = 1.0; n->GetFloatProperty( "pointsize", pointSize, renderer); switch (data.pointSpec) { //TODO: look up representation in a representationlookuptable case PTSTART: //cube m_CubeSources[pointID]->SetXLength(pointSize); m_CubeSources[pointID]->SetYLength(pointSize); m_CubeSources[pointID]->SetZLength(pointSize); //m_CubeSources[pointID]->SetCenter(pos[0], pos[1], pos[2]); break; case PTCORNER: //cone m_ConeSources[pointID]->SetRadius(pointSize/2); m_ConeSources[pointID]->SetHeight(pointSize); m_ConeSources[pointID]->SetResolution(2); // two crossed triangles. Maybe introduce an extra property for //m_ConeSources[pointID]->SetCenter(pos[0], pos[1], pos[2]); break; case PTEDGE: // cylinder m_CylinderSources[pointID]->SetRadius(pointSize/2); m_CylinderSources[pointID]->SetHeight(pointSize); m_CylinderSources[pointID]->CappingOn(); m_CylinderSources[pointID]->SetResolution(6); //m_CylinderSources[pointID]->SetCenter(pos[0], pos[1], pos[2]); break; case PTUNDEFINED: // sphere case PTEND: default: m_SphereSources[pointID]->SetRadius(pointSize/2); m_SphereSources[pointID]->SetThetaResolution(10); m_SphereSources[pointID]->SetPhiResolution(10); //m_SphereSources[pointID]->SetCenter(pos[0], pos[1], pos[2]); break; } // set position mitk::Point3D pos = pIt->Value(); aIt->second.first->SetPosition(pos[0], pos[1], pos[2]); // selectedcolor & color float color[3]; if (data.selected) { if(!n->GetColor(color, renderer, "selectedcolor")) n->GetColor(color, renderer); } else { mitk::BaseProperty* a = n->GetProperty("colorLookupTable", renderer); mitk::LookupTableProperty* b = dynamic_cast(a); if (b != NULL) { mitk::LookupTable::Pointer c = b->GetLookupTable(); vtkLookupTable *d = c->GetVtkLookupTable(); double *e=d->GetTableValue(pointID); color[0]=e[0]; color[1]=e[1]; color[2]=e[2]; } else { if(!n->GetColor(color, renderer, "unselectedcolor")) n->GetColor(color, renderer); } } // TODO: What about "color" property? 2D Mapper only uses unselected and selected color properties a->GetProperty()->SetColor(color[0], color[1], color[2]); // TODO: label property } //TODO test different pointSpec // TODO "line width" "show contour" "contourcolor" "contoursize" "close contour" "show label", "label" // TODO "show points" vs "visibility" - is visibility evaluated at all? in a superclass maybe? // TODO create lookup tables for all properties that should be evaluated per point. also create editor widgets for these lookup tables! // TODO check if property changes and pointset changes are reflected in the render window immediately. // TODO check behavior with large PointSets // TODO check for memory leaks on adding/deleting points } void mitk::EnhancedPointSetVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer * renderer ) { ApplyProperties(renderer); } void mitk::EnhancedPointSetVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) { // TODO: apply new transform if time step changed //vtkLinearTransform * vtktransform = // this->GetDataNode()->GetVtkTransform(this->GetTimestep()); //m_SelectedActor->SetUserTransform(vtktransform); //m_UnselectedActor->SetUserTransform(vtktransform); //m_ContourActor->SetUserTransform(vtktransform); } void mitk::EnhancedPointSetVtkMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "line width", mitk::IntProperty::New(2), renderer, overwrite ); node->AddProperty( "pointsize", mitk::FloatProperty::New(1.0), renderer, overwrite); node->AddProperty( "selectedcolor", mitk::ColorProperty::New(1.0f, 1.0f, 0.0f), renderer, overwrite); //yellow for selected node->AddProperty( "unselectedcolor", mitk::ColorProperty::New(0.5f, 1.0f, 0.5f), renderer, overwrite); // middle green for unselected node->AddProperty( "color", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite); // red as standard node->AddProperty( "show contour", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "contourcolor", mitk::ColorProperty::New(1.0f, 0.0f, 0.0f), renderer, overwrite); node->AddProperty( "contoursize", mitk::FloatProperty::New(0.5), renderer, overwrite ); node->AddProperty( "show points", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "show label", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "label", mitk::StringProperty::New("P"), renderer, overwrite ); node->AddProperty( "opacity", mitk::FloatProperty::New(1.0), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } void mitk::EnhancedPointSetVtkMapper3D::DeleteVtkObject( vtkObject* o) { if (o != NULL) o->Delete(); } void mitk::EnhancedPointSetVtkMapper3D::RemoveEntryFromSourceMaps( mitk::PointSet::PointIdentifier pointID ) { ActorMap::iterator aIt = m_PointActors.find(pointID); if (aIt == m_PointActors.end()) return; switch (aIt->second.second) // erase in old map { //TODO: look up representation in a representationlookuptable case PTSTART: //cube m_CubeSources[pointID]->Delete(); m_CubeSources.erase(pointID); break; case PTCORNER: //cone m_ConeSources[pointID]->Delete(); m_ConeSources.erase(pointID); break; case PTEDGE: // cylinder m_CylinderSources[pointID]->Delete(); m_CylinderSources.erase(pointID); break; case PTUNDEFINED: // sphere case PTEND: default: m_SphereSources[pointID]->Delete(); m_SphereSources.erase(pointID); break; } } diff --git a/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.h b/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.h index 445bac2205..84ebcf36c2 100644 --- a/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.h +++ b/Modules/MitkExt/Rendering/mitkEnhancedPointSetVtkMapper3D.h @@ -1,124 +1,123 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKEnhancedPointSetVtkMapper3D_H_HEADER_INCLUDED_C1907273 #define MITKEnhancedPointSetVtkMapper3D_H_HEADER_INCLUDED_C1907273 #include "mitkCommon.h" #include "MitkExtExports.h" -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include "mitkBaseRenderer.h" #include "mitkPointSet.h" #include "mitkVector.h" class vtkActor; class vtkAssembly; class vtkSphereSource; class vtkCubeSource; class vtkConeSource; class vtkCylinderSource; class vtkTubeFilter; class vtkProp; namespace mitk { /** * \brief Alternative Vtk-based 3D mapper for mitk::PointSet * * This class renders mitk::PointSet objects in 3D views. It resembles the * standard mitk::PointSetVtkMapper3D, but is designed to enable single * points to be rendered with individual appearances. * * Instead of assembling one vtkPolyData object containing all points, * a list of VTK source objects (spheres, cubes, cones, ...) is maintained. * Therefore, the application can change the appearance and/or type of a * specific point at runtime, without having to rebuild the * * You should use this class instead of the standard mapper if you * * - change the PointSet very often (by adding or removing points) * - need different representations for points (+++) * - want to change the point representation frequently (+++) * * Note: the class is still in experimental stage, and the points above * marked with (+++) are not yet working correctly. Also, drawing lines * between points (contour mode) is not yet supported. The class will be * extended so that point representations are stored in a lookup table, * which is indexed by point data from the rendered PointSet. * * \warn This mapper requires the PointData container to be the same size * as the point container. * * \sa PointSetVtkMapper3D */ - class MitkExt_EXPORT EnhancedPointSetVtkMapper3D : public VtkMapper3D + class MitkExt_EXPORT EnhancedPointSetVtkMapper3D : public VtkMapper { public: - mitkClassMacro(EnhancedPointSetVtkMapper3D, VtkMapper3D); + mitkClassMacro(EnhancedPointSetVtkMapper3D, VtkMapper); itkNewMacro(Self); virtual const mitk::PointSet* GetInput(); virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer); static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); void ReleaseGraphicsResources(vtkWindow *renWin); protected: EnhancedPointSetVtkMapper3D(); virtual ~EnhancedPointSetVtkMapper3D(); void RemoveEntryFromSourceMaps( mitk::PointSet::PointIdentifier pointID ); void DeleteVtkObject(vtkObject* o); // functor for stl_each in destructor // update all vtk sources, mappers, actors with current data and properties void UpdateVtkObjects(); - virtual void GenerateData(); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); virtual void ApplyProperties(mitk::BaseRenderer* renderer); typedef mitk::PointSet::PointIdentifier PointIdentifier; typedef std::map SphereSourceMap; typedef std::map CubeSourceMap; typedef std::map ConeSourceMap; typedef std::map CylinderSourceMap; typedef std::pair ActorAndPointType; typedef std::map ActorMap; SphereSourceMap m_SphereSources; // stores all sphere sources CubeSourceMap m_CubeSources; // stores all cube sources ConeSourceMap m_ConeSources; // stores all cone sources CylinderSourceMap m_CylinderSources; // stores all cylinder sources ActorMap m_PointActors; // stores an actor for each point(referenced by its ID) and the currently used pointspec = which source type is generating the polydata vtkActor* m_Contour; vtkTubeFilter* m_ContourSource; vtkAssembly* m_PropAssembly; // this contains everything, this will be returned by GetVtkProp() }; } // namespace mitk #endif /* MITKEnhancedPointSetVtkMapper3D_H_HEADER_INCLUDED_C1907273 */ diff --git a/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.cpp b/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.cpp index 5265b2e98b..2d66b1637b 100644 --- a/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.cpp +++ b/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.cpp @@ -1,704 +1,708 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #define GPU_INFO MITK_INFO("mapper.vr") #define GPU_WARN MITK_WARN("mapper.vr") #define GPU_ERROR MITK_ERROR("mapper.vr") #include "mitkGPUVolumeMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkLevelWindow.h" #include "mitkColorProperty.h" #include "mitkLevelWindowProperty.h" #include "mitkLookupTableProperty.h" #include "mitkTransferFunctionProperty.h" #include "mitkTransferFunctionInitializer.h" #include "mitkColorProperty.h" #include "mitkVtkPropRenderer.h" #include "mitkRenderingManager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) #include "vtkMitkGPUVolumeRayCastMapper.h" #endif #include "vtkOpenGLGPUVolumeRayCastMapper.h" #include "vtkMitkOpenGLVolumeTextureMapper3D.h" const mitk::Image* mitk::GPUVolumeMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } void mitk::GPUVolumeMapper3D::MitkRenderVolumetricGeometry(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - VtkMapper3D::MitkRenderVolumetricGeometry(renderer); + VtkMapper::MitkRenderVolumetricGeometry(renderer); if(ls->m_gpuInitialized) ls->m_MapperGPU->UpdateMTime(); } bool mitk::GPUVolumeMapper3D::InitGPU(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if(ls->m_gpuInitialized) return ls->m_gpuSupported; GPU_INFO << "initializing gpu-slicing-vr (vtkMitkOpenGLVolumeTextureMapper3D)"; ls->m_MapperGPU = vtkSmartPointer::New(); ls->m_MapperGPU->SetUseCompressedTexture(false); ls->m_MapperGPU->SetSampleDistance(1.0); ls->m_VolumePropertyGPU = vtkSmartPointer::New(); ls->m_VolumePropertyGPU->ShadeOn(); ls->m_VolumePropertyGPU->SetAmbient (0.25f); //0.05f ls->m_VolumePropertyGPU->SetDiffuse (0.50f); //0.45f ls->m_VolumePropertyGPU->SetSpecular(0.40f); //0.50f ls->m_VolumePropertyGPU->SetSpecularPower(16.0f); ls->m_VolumePropertyGPU->SetInterpolationTypeToLinear(); ls->m_VolumeGPU = vtkSmartPointer::New(); ls->m_VolumeGPU->SetMapper( ls->m_MapperGPU ); ls->m_VolumeGPU->SetProperty( ls->m_VolumePropertyGPU ); ls->m_VolumeGPU->VisibilityOn(); ls->m_MapperGPU->SetInput( this->m_UnitSpacingImageFilter->GetOutput() ); ls->m_gpuSupported = ls->m_MapperGPU->IsRenderSupported(renderer->GetVtkRenderer(),ls->m_VolumePropertyGPU); ls->m_gpuInitialized = true; return ls->m_gpuSupported; } void mitk::GPUVolumeMapper3D::InitCPU(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if(ls->m_cpuInitialized) return; int numThreads = itk::MultiThreader::GetGlobalDefaultNumberOfThreads(); GPU_INFO << "initializing cpu-raycast-vr (vtkFixedPointVolumeRayCastMapper) (" << numThreads << " threads)"; ls->m_MapperCPU = vtkSmartPointer::New(); ls->m_MapperCPU->SetSampleDistance(1.0); // ls->m_MapperCPU->LockSampleDistanceToInputSpacingOn(); ls->m_MapperCPU->SetImageSampleDistance(1.0); ls->m_MapperCPU->IntermixIntersectingGeometryOn(); ls->m_MapperCPU->SetAutoAdjustSampleDistances(0); ls->m_MapperCPU->SetNumberOfThreads( numThreads ); ls->m_VolumePropertyCPU = vtkSmartPointer::New(); ls->m_VolumePropertyCPU->ShadeOn(); ls->m_VolumePropertyCPU->SetAmbient (0.10f); //0.05f ls->m_VolumePropertyCPU->SetDiffuse (0.50f); //0.45f ls->m_VolumePropertyCPU->SetSpecular(0.40f); //0.50f ls->m_VolumePropertyCPU->SetSpecularPower(16.0f); ls->m_VolumePropertyCPU->SetInterpolationTypeToLinear(); ls->m_VolumeCPU = vtkSmartPointer::New(); ls->m_VolumeCPU->SetMapper( ls->m_MapperCPU ); ls->m_VolumeCPU->SetProperty( ls->m_VolumePropertyCPU ); ls->m_VolumeCPU->VisibilityOn(); ls->m_MapperCPU->SetInput( m_UnitSpacingImageFilter->GetOutput() );//m_Resampler->GetOutput()); ls->m_cpuInitialized=true; } void mitk::GPUVolumeMapper3D::DeinitGPU(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if(ls->m_gpuInitialized) { GPU_INFO << "deinitializing gpu-slicing-vr"; ls->m_VolumePropertyGPU = NULL; ls->m_MapperGPU = NULL; ls->m_VolumeGPU = NULL; ls->m_gpuInitialized=false; } } void mitk::GPUVolumeMapper3D::DeinitCPU(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if(!ls->m_cpuInitialized) return; GPU_INFO << "deinitializing cpu-raycast-vr"; ls->m_VolumePropertyCPU = NULL; ls->m_MapperCPU = NULL; ls->m_VolumeCPU = NULL; ls->m_cpuInitialized=false; } mitk::GPUVolumeMapper3D::GPUVolumeMapper3D() { m_VolumeNULL=0; m_commonInitialized=false; } mitk::GPUVolumeMapper3D::~GPUVolumeMapper3D() { DeinitCommon(); } void mitk::GPUVolumeMapper3D::InitCommon() { if(m_commonInitialized) return; m_UnitSpacingImageFilter = vtkSmartPointer::New(); m_UnitSpacingImageFilter->SetOutputSpacing( 1.0, 1.0, 1.0 ); CreateDefaultTransferFunctions(); m_commonInitialized=true; } void mitk::GPUVolumeMapper3D::DeinitCommon() { if(!m_commonInitialized) return; m_commonInitialized=false; } bool mitk::GPUVolumeMapper3D::IsRenderable(mitk::BaseRenderer* renderer) { - if(!IsVisible(renderer)) - return false; if(!GetDataNode()) return false; - bool value = false; + DataNode* node = GetDataNode(); + + bool visible = true; + node->GetVisibility(visible, renderer, "visible"); - if(!GetDataNode()->GetBoolProperty("volumerendering",value,renderer)) + if(!visible) return false; + + bool value = false; + if(!node->GetBoolProperty("volumerendering",value,renderer)); return false; if(!value) return false; mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); if ( !input || !input->IsInitialized() ) return false; vtkImageData *inputData = input->GetVtkImageData( this->GetTimestep() ); if(inputData==NULL) return false; return true; } void mitk::GPUVolumeMapper3D::InitVtkMapper(mitk::BaseRenderer* renderer) { // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) if(IsRAYEnabled(renderer)) { DeinitCPU(renderer); DeinitGPU(renderer); if(!InitRAY(renderer)) { GPU_WARN << "hardware renderer can't initialize ... falling back to software renderer"; goto fallback; } } else #endif if(IsGPUEnabled(renderer)) { DeinitCPU(renderer); // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) DeinitRAY(renderer); #endif if(!InitGPU(renderer)) { GPU_WARN << "hardware renderer can't initialize ... falling back to software renderer"; goto fallback; } } else { fallback: DeinitGPU(renderer); // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) DeinitRAY(renderer); #endif InitCPU(renderer); } } vtkProp *mitk::GPUVolumeMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { if(!IsRenderable(renderer)) { if(!m_VolumeNULL) { m_VolumeNULL = vtkSmartPointer::New(); m_VolumeNULL->VisibilityOff(); } return m_VolumeNULL; } InitCommon(); InitVtkMapper( renderer ); LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) if(ls->m_rayInitialized) return ls->m_VolumeRAY; #endif if(ls->m_gpuInitialized) return ls->m_VolumeGPU; return ls->m_VolumeCPU; } void mitk::GPUVolumeMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { if(!IsRenderable(renderer)) return; InitCommon(); InitVtkMapper( renderer ); mitk::Image *input = const_cast< mitk::Image * >( this->GetInput() ); vtkImageData *inputData = input->GetVtkImageData( this->GetTimestep() ); m_UnitSpacingImageFilter->SetInput( inputData ); LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) if(ls->m_rayInitialized) { GenerateDataRAY(renderer); } else #endif if(ls->m_gpuInitialized) { GenerateDataGPU(renderer); } else { GenerateDataCPU(renderer); } // UpdateTransferFunctions UpdateTransferFunctions( renderer ); } void mitk::GPUVolumeMapper3D::GenerateDataGPU( mitk::BaseRenderer *renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool useCompression = false; GetDataNode()->GetBoolProperty("volumerendering.gpu.usetexturecompression",useCompression,renderer); ls->m_MapperGPU->SetUseCompressedTexture(useCompression); if( IsLODEnabled(renderer) && mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ) == 0 ) ls->m_MapperGPU->SetSampleDistance(2.0); else ls->m_MapperGPU->SetSampleDistance(1.0); // Updating shadings { float value=0; if(GetDataNode()->GetFloatProperty("volumerendering.gpu.ambient",value,renderer)) ls->m_VolumePropertyGPU->SetAmbient(value); if(GetDataNode()->GetFloatProperty("volumerendering.gpu.diffuse",value,renderer)) ls->m_VolumePropertyGPU->SetDiffuse(value); if(GetDataNode()->GetFloatProperty("volumerendering.gpu.specular",value,renderer)) ls->m_VolumePropertyGPU->SetSpecular(value); if(GetDataNode()->GetFloatProperty("volumerendering.gpu.specular.power",value,renderer)) ls->m_VolumePropertyGPU->SetSpecularPower(value); } } void mitk::GPUVolumeMapper3D::GenerateDataCPU( mitk::BaseRenderer *renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); int nextLod = mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ); if( IsLODEnabled(renderer) && nextLod == 0 ) { ls->m_MapperCPU->SetImageSampleDistance(3.5); ls->m_MapperCPU->SetSampleDistance(1.25); ls->m_VolumePropertyCPU->SetInterpolationTypeToNearest(); } else { ls->m_MapperCPU->SetImageSampleDistance(1.0); ls->m_MapperCPU->SetSampleDistance(1.0); ls->m_VolumePropertyCPU->SetInterpolationTypeToLinear(); } // Check raycasting mode if(IsMIPEnabled(renderer)) ls->m_MapperCPU->SetBlendModeToMaximumIntensity(); else ls->m_MapperCPU->SetBlendModeToComposite(); // Updating shadings { float value=0; if(GetDataNode()->GetFloatProperty("volumerendering.cpu.ambient",value,renderer)) ls->m_VolumePropertyCPU->SetAmbient(value); if(GetDataNode()->GetFloatProperty("volumerendering.cpu.diffuse",value,renderer)) ls->m_VolumePropertyCPU->SetDiffuse(value); if(GetDataNode()->GetFloatProperty("volumerendering.cpu.specular",value,renderer)) ls->m_VolumePropertyCPU->SetSpecular(value); if(GetDataNode()->GetFloatProperty("volumerendering.cpu.specular.power",value,renderer)) ls->m_VolumePropertyCPU->SetSpecularPower(value); } } void mitk::GPUVolumeMapper3D::CreateDefaultTransferFunctions() { m_DefaultOpacityTransferFunction = vtkSmartPointer::New(); m_DefaultOpacityTransferFunction->AddPoint( 0.0, 0.0 ); m_DefaultOpacityTransferFunction->AddPoint( 255.0, 0.8 ); m_DefaultOpacityTransferFunction->ClampingOn(); m_DefaultGradientTransferFunction = vtkSmartPointer::New(); m_DefaultGradientTransferFunction->AddPoint( 0.0, 0.0 ); m_DefaultGradientTransferFunction->AddPoint( 255.0, 0.8 ); m_DefaultGradientTransferFunction->ClampingOn(); m_DefaultColorTransferFunction = vtkSmartPointer::New(); m_DefaultColorTransferFunction->AddRGBPoint( 0.0, 0.0, 0.0, 0.0 ); m_DefaultColorTransferFunction->AddRGBPoint( 127.5, 1, 1, 0.0 ); m_DefaultColorTransferFunction->AddRGBPoint( 255.0, 0.8, 0.2, 0 ); m_DefaultColorTransferFunction->ClampingOn(); m_BinaryOpacityTransferFunction = vtkSmartPointer::New(); m_BinaryOpacityTransferFunction->AddPoint( 0, 0.0 ); m_BinaryOpacityTransferFunction->AddPoint( 1, 1.0 ); m_BinaryGradientTransferFunction = vtkSmartPointer::New(); m_BinaryGradientTransferFunction->AddPoint( 0.0, 1.0 ); m_BinaryColorTransferFunction = vtkSmartPointer::New(); } void mitk::GPUVolumeMapper3D::UpdateTransferFunctions( mitk::BaseRenderer * renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); vtkPiecewiseFunction *opacityTransferFunction = m_DefaultOpacityTransferFunction; vtkPiecewiseFunction *gradientTransferFunction = m_DefaultGradientTransferFunction; vtkColorTransferFunction *colorTransferFunction = m_DefaultColorTransferFunction; bool isBinary = false; GetDataNode()->GetBoolProperty("binary", isBinary, renderer); if(isBinary) { opacityTransferFunction = m_BinaryOpacityTransferFunction; gradientTransferFunction = m_BinaryGradientTransferFunction; colorTransferFunction = m_BinaryColorTransferFunction; colorTransferFunction->RemoveAllPoints(); float rgb[3]; if( !GetDataNode()->GetColor( rgb,renderer ) ) rgb[0]=rgb[1]=rgb[2]=1; colorTransferFunction->AddRGBPoint( 0,rgb[0],rgb[1],rgb[2] ); colorTransferFunction->Modified(); } else { mitk::TransferFunctionProperty *transferFunctionProp = dynamic_cast(this->GetDataNode()->GetProperty("TransferFunction",renderer)); if( transferFunctionProp ) { opacityTransferFunction = transferFunctionProp->GetValue()->GetScalarOpacityFunction(); gradientTransferFunction = transferFunctionProp->GetValue()->GetGradientOpacityFunction(); colorTransferFunction = transferFunctionProp->GetValue()->GetColorTransferFunction(); } } if(ls->m_gpuInitialized) { ls->m_VolumePropertyGPU->SetColor( colorTransferFunction ); ls->m_VolumePropertyGPU->SetScalarOpacity( opacityTransferFunction ); ls->m_VolumePropertyGPU->SetGradientOpacity( gradientTransferFunction ); } // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) if(ls->m_rayInitialized) { ls->m_VolumePropertyRAY->SetColor( colorTransferFunction ); ls->m_VolumePropertyRAY->SetScalarOpacity( opacityTransferFunction ); ls->m_VolumePropertyRAY->SetGradientOpacity( gradientTransferFunction ); } #endif if(ls->m_cpuInitialized) { ls->m_VolumePropertyCPU->SetColor( colorTransferFunction ); ls->m_VolumePropertyCPU->SetScalarOpacity( opacityTransferFunction ); ls->m_VolumePropertyCPU->SetGradientOpacity( gradientTransferFunction ); } } void mitk::GPUVolumeMapper3D::ApplyProperties(vtkActor* /*actor*/, mitk::BaseRenderer* /*renderer*/) { //GPU_INFO << "ApplyProperties"; } void mitk::GPUVolumeMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { //GPU_INFO << "SetDefaultProperties"; node->AddProperty( "volumerendering", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "volumerendering.usemip", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "volumerendering.uselod", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "volumerendering.cpu.ambient", mitk::FloatProperty::New( 0.10f ), renderer, overwrite ); node->AddProperty( "volumerendering.cpu.diffuse", mitk::FloatProperty::New( 0.50f ), renderer, overwrite ); node->AddProperty( "volumerendering.cpu.specular", mitk::FloatProperty::New( 0.40f ), renderer, overwrite ); node->AddProperty( "volumerendering.cpu.specular.power", mitk::FloatProperty::New( 16.0f ), renderer, overwrite ); bool usegpu = true; #ifdef __APPLE__ usegpu = false; node->AddProperty( "volumerendering.uselod", mitk::BoolProperty::New( true ), renderer, overwrite ); #endif node->AddProperty( "volumerendering.usegpu", mitk::BoolProperty::New( usegpu ), renderer, overwrite ); // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) node->AddProperty( "volumerendering.useray", mitk::BoolProperty::New( false ), renderer, overwrite ); node->AddProperty( "volumerendering.ray.ambient", mitk::FloatProperty::New( 0.25f ), renderer, overwrite ); node->AddProperty( "volumerendering.ray.diffuse", mitk::FloatProperty::New( 0.50f ), renderer, overwrite ); node->AddProperty( "volumerendering.ray.specular", mitk::FloatProperty::New( 0.40f ), renderer, overwrite ); node->AddProperty( "volumerendering.ray.specular.power", mitk::FloatProperty::New( 16.0f ), renderer, overwrite ); #endif node->AddProperty( "volumerendering.gpu.ambient", mitk::FloatProperty::New( 0.25f ), renderer, overwrite ); node->AddProperty( "volumerendering.gpu.diffuse", mitk::FloatProperty::New( 0.50f ), renderer, overwrite ); node->AddProperty( "volumerendering.gpu.specular", mitk::FloatProperty::New( 0.40f ), renderer, overwrite ); node->AddProperty( "volumerendering.gpu.specular.power", mitk::FloatProperty::New( 16.0f ), renderer, overwrite ); node->AddProperty( "volumerendering.gpu.usetexturecompression", mitk::BoolProperty ::New( false ), renderer, overwrite ); node->AddProperty( "volumerendering.gpu.reducesliceartifacts" , mitk::BoolProperty ::New( false ), renderer, overwrite ); node->AddProperty( "binary", mitk::BoolProperty::New( false ), renderer, overwrite ); mitk::Image::Pointer image = dynamic_cast(node->GetData()); if(image.IsNotNull() && image->IsInitialized()) { if((overwrite) || (node->GetProperty("levelwindow", renderer)==NULL)) { mitk::LevelWindowProperty::Pointer levWinProp = mitk::LevelWindowProperty::New(); mitk::LevelWindow levelwindow; levelwindow.SetAuto( image ); levWinProp->SetLevelWindow( levelwindow ); node->SetProperty( "levelwindow", levWinProp, renderer ); } if((overwrite) || (node->GetProperty("TransferFunction", renderer)==NULL)) { // add a default transfer function mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); mitk::TransferFunctionInitializer::Pointer tfInit = mitk::TransferFunctionInitializer::New(tf); tfInit->SetTransferFunctionMode(0); node->SetProperty ( "TransferFunction", mitk::TransferFunctionProperty::New ( tf.GetPointer() ) ); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } bool mitk::GPUVolumeMapper3D::IsLODEnabled( mitk::BaseRenderer * renderer ) const { bool value = false; return GetDataNode()->GetBoolProperty("volumerendering.uselod",value,renderer) && value; } bool mitk::GPUVolumeMapper3D::IsMIPEnabled( mitk::BaseRenderer * renderer ) { bool value = false; return GetDataNode()->GetBoolProperty("volumerendering.usemip",value,renderer) && value; } bool mitk::GPUVolumeMapper3D::IsGPUEnabled( mitk::BaseRenderer * renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool value = false; return ls->m_gpuSupported && GetDataNode()->GetBoolProperty("volumerendering.usegpu",value,renderer) && value; } // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) bool mitk::GPUVolumeMapper3D::InitRAY(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if(ls->m_rayInitialized) return ls->m_raySupported; GPU_INFO << "initializing gpu-raycast-vr (vtkOpenGLGPUVolumeRayCastMapper)"; ls->m_MapperRAY = vtkSmartPointer::New(); ls->m_MapperRAY->SetAutoAdjustSampleDistances(0); ls->m_MapperRAY->SetSampleDistance(1.0); ls->m_VolumePropertyRAY = vtkSmartPointer::New(); ls->m_VolumePropertyRAY->ShadeOn(); ls->m_VolumePropertyRAY->SetAmbient (0.25f); //0.05f ls->m_VolumePropertyRAY->SetDiffuse (0.50f); //0.45f ls->m_VolumePropertyRAY->SetSpecular(0.40f); //0.50f ls->m_VolumePropertyRAY->SetSpecularPower(16.0f); ls->m_VolumePropertyRAY->SetInterpolationTypeToLinear(); ls->m_VolumeRAY = vtkSmartPointer::New(); ls->m_VolumeRAY->SetMapper( ls->m_MapperRAY ); ls->m_VolumeRAY->SetProperty( ls->m_VolumePropertyRAY ); ls->m_VolumeRAY->VisibilityOn(); ls->m_MapperRAY->SetInput( this->m_UnitSpacingImageFilter->GetOutput() ); ls->m_raySupported = ls->m_MapperRAY->IsRenderSupported(renderer->GetRenderWindow(),ls->m_VolumePropertyRAY); ls->m_rayInitialized = true; return ls->m_raySupported; } void mitk::GPUVolumeMapper3D::DeinitRAY(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if(ls->m_rayInitialized) { GPU_INFO << "deinitializing gpu-raycast-vr"; ls->m_MapperRAY = NULL; ls->m_VolumePropertyRAY = NULL; //Here ReleaseGraphicsResources has to be called to avoid VTK error messages. //This seems like a VTK bug, because ReleaseGraphicsResources() is ment for internal use, //but you cannot just delete the object (last smartpointer reference) without getting the //VTK error. ls->m_VolumeRAY->ReleaseGraphicsResources(renderer->GetVtkRenderer()->GetRenderWindow()); ls->m_VolumeRAY = NULL; ls->m_rayInitialized=false; } } void mitk::GPUVolumeMapper3D::GenerateDataRAY( mitk::BaseRenderer *renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); if( IsLODEnabled(renderer) && mitk::RenderingManager::GetInstance()->GetNextLOD( renderer ) == 0 ) ls->m_MapperRAY->SetImageSampleDistance(4.0); else ls->m_MapperRAY->SetImageSampleDistance(1.0); // Check raycasting mode if(IsMIPEnabled(renderer)) ls->m_MapperRAY->SetBlendModeToMaximumIntensity(); else ls->m_MapperRAY->SetBlendModeToComposite(); // Updating shadings { float value=0; if(GetDataNode()->GetFloatProperty("volumerendering.ray.ambient",value,renderer)) ls->m_VolumePropertyRAY->SetAmbient(value); if(GetDataNode()->GetFloatProperty("volumerendering.ray.diffuse",value,renderer)) ls->m_VolumePropertyRAY->SetDiffuse(value); if(GetDataNode()->GetFloatProperty("volumerendering.ray.specular",value,renderer)) ls->m_VolumePropertyRAY->SetSpecular(value); if(GetDataNode()->GetFloatProperty("volumerendering.ray.specular.power",value,renderer)) ls->m_VolumePropertyRAY->SetSpecularPower(value); } } bool mitk::GPUVolumeMapper3D::IsRAYEnabled( mitk::BaseRenderer * renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); bool value = false; return ls->m_raySupported && GetDataNode()->GetBoolProperty("volumerendering.useray",value,renderer) && value; } #endif diff --git a/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.h b/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.h index 49ff32f358..7622549925 100644 --- a/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.h +++ b/Modules/MitkExt/Rendering/mitkGPUVolumeMapper3D.h @@ -1,197 +1,197 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKGPUVOLUMEMAPPER3D_H_HEADER_INCLUDED #define MITKGPUVOLUMEMAPPER3D_H_HEADER_INCLUDED //MITK #include "mitkCommon.h" #include "MitkExtExports.h" #include "mitkBaseRenderer.h" #include "mitkImage.h" -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include "vtkMitkVolumeTextureMapper3D.h" //VTK #include #include #include #include #include // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) #include "vtkMitkGPUVolumeRayCastMapper.h" #endif namespace mitk { /************************************************************************/ /* Properties that influence the mapper are: * * - \b "level window": for the level window of the volume data * - \b "LookupTable" : for the lookup table of the volume data * - \b "TransferFunction" (mitk::TransferFunctionProperty): for the used transfer function of the volume data ************************************************************************/ //##Documentation //## @brief Vtk-based mapper for VolumeData //## //## @ingroup Mapper -class MitkExt_EXPORT GPUVolumeMapper3D : public VtkMapper3D +class MitkExt_EXPORT GPUVolumeMapper3D : public VtkMapper { public: - mitkClassMacro(GPUVolumeMapper3D, VtkMapper3D); + mitkClassMacro(GPUVolumeMapper3D, VtkMapper); itkNewMacro(Self); virtual const mitk::Image* GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); virtual void ApplyProperties(vtkActor* actor, mitk::BaseRenderer* renderer); static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); /** Returns true if this Mapper currently allows for Level-of-Detail rendering. * This reflects whether this Mapper currently invokes StartEvent, EndEvent, and * ProgressEvent on BaseRenderer. */ virtual bool IsLODEnabled( BaseRenderer *renderer = NULL ) const; bool IsMIPEnabled( BaseRenderer *renderer = NULL ); bool IsGPUEnabled( BaseRenderer *renderer = NULL ); bool IsRAYEnabled( BaseRenderer *renderer = NULL ); virtual void MitkRenderVolumetricGeometry(mitk::BaseRenderer* renderer); protected: GPUVolumeMapper3D(); virtual ~GPUVolumeMapper3D(); bool IsRenderable(mitk::BaseRenderer* renderer); void InitCommon(); void DeinitCommon(); void InitCPU(mitk::BaseRenderer* renderer); void DeinitCPU(mitk::BaseRenderer* renderer); void GenerateDataCPU(mitk::BaseRenderer* renderer); bool InitGPU(mitk::BaseRenderer* renderer); void DeinitGPU(mitk::BaseRenderer* renderer); void GenerateDataGPU(mitk::BaseRenderer* renderer); // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) bool InitRAY(mitk::BaseRenderer* renderer); void DeinitRAY(mitk::BaseRenderer* renderer); void GenerateDataRAY(mitk::BaseRenderer* renderer); #endif void InitVtkMapper(mitk::BaseRenderer* renderer); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); void CreateDefaultTransferFunctions(); void UpdateTransferFunctions( mitk::BaseRenderer *renderer ); vtkSmartPointer m_VolumeNULL; bool m_commonInitialized; vtkSmartPointer m_UnitSpacingImageFilter; vtkSmartPointer m_DefaultOpacityTransferFunction; vtkSmartPointer m_DefaultGradientTransferFunction; vtkSmartPointer m_DefaultColorTransferFunction; vtkSmartPointer m_BinaryOpacityTransferFunction; vtkSmartPointer m_BinaryGradientTransferFunction; vtkSmartPointer m_BinaryColorTransferFunction; class LocalStorage : public mitk::Mapper::BaseLocalStorage { public: bool m_cpuInitialized; vtkSmartPointer m_VolumeCPU; vtkSmartPointer m_MapperCPU; vtkSmartPointer m_VolumePropertyCPU; bool m_gpuSupported; bool m_gpuInitialized; vtkSmartPointer m_VolumeGPU; vtkSmartPointer m_MapperGPU; vtkSmartPointer m_VolumePropertyGPU; // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) bool m_raySupported; bool m_rayInitialized; vtkSmartPointer m_VolumeRAY; vtkSmartPointer m_MapperRAY; vtkSmartPointer m_VolumePropertyRAY; #endif LocalStorage() { m_cpuInitialized = false; m_gpuInitialized = false; m_gpuSupported = true; // assume initially gpu slicing is supported // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) m_rayInitialized = false; m_raySupported = true; // assume initially gpu raycasting is supported #endif } ~LocalStorage() { if(m_cpuInitialized) { m_cpuInitialized=false; } if(m_gpuInitialized) { m_gpuInitialized=false; } // Only with VTK 5.6 or above #if ((VTK_MAJOR_VERSION > 5) || ((VTK_MAJOR_VERSION==5) && (VTK_MINOR_VERSION>=6) )) if(m_rayInitialized) { m_rayInitialized=false; } #endif } }; mitk::Mapper::LocalStorageHandler m_LSH; }; } // namespace mitk #endif /* MITKVOLUMEDATAVTKMAPPER3D_H_HEADER_INCLUDED */ diff --git a/Modules/MitkExt/Rendering/mitkLineMapper2D.cpp b/Modules/MitkExt/Rendering/mitkLineMapper2D.cpp index 432b016abc..19560e23ca 100644 --- a/Modules/MitkExt/Rendering/mitkLineMapper2D.cpp +++ b/Modules/MitkExt/Rendering/mitkLineMapper2D.cpp @@ -1,138 +1,140 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkLineMapper2D.h" #include "mitkPointSet.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include #include "mitkPointSet.h" #include "mitkGL.h" mitk::LineMapper2D::LineMapper2D() : mitk::PointSetGLMapper2D() { } mitk::LineMapper2D::~LineMapper2D() { } const mitk::PointSet *mitk::LineMapper2D::GetInput(void) { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } void mitk::LineMapper2D::Paint(mitk::BaseRenderer * renderer) { - if(IsVisible(renderer)==false) - return; + + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + if(!visible) return; bool updateNeccesary = true;//!!!! @TODO !??!! if (updateNeccesary) { mitk::PointSet::Pointer input = const_cast(this->GetInput()); mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert(displayGeometry.IsNotNull()); //apply color and opacity read from the PropertyList - ApplyProperties(renderer); + ApplyColorAndOpacityProperties(renderer); vtkLinearTransform* transform = GetDataNode()->GetVtkTransform(); //List of the Points PointSet::DataType::PointsContainerConstIterator it, end; it = input->GetPointSet()->GetPoints()->Begin(); end = input->GetPointSet()->GetPoints()->End();//the last before end, because lines from n to n+1 if (end!=it) // otherwise PointSet is empty end--; //bool list for the selection of the points PointSet::DataType::PointDataContainerIterator selIt, selItNext; selIt=input->GetPointSet()->GetPointData()->Begin(); int j=0; while(it!=end) { mitk::Point3D p, q, projected_p, projected_q; float vtkp[3]; itk2vtk(it->Value(), vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); //next point n+1 it++; itk2vtk(it->Value(), vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,q); it--; displayGeometry->Project(p, projected_p); displayGeometry->Project(q, projected_q); Vector3D diffp=p-projected_p, diffq=q-projected_q; if((diffp.GetSquaredNorm()<4.0) && (diffq.GetSquaredNorm()<4.0)) { Point2D p2d, q2d, tmp; displayGeometry->Map(projected_p, p2d); displayGeometry->WorldToDisplay(p2d, p2d); displayGeometry->Map(projected_q, q2d); displayGeometry->WorldToDisplay(q2d, q2d); //outlined, cause iterators behave strange and multiple points can't be selected anyway by now! //selItNext = selIt++;//Iterator to the next Element, cause only when the two points ar selected, then the Line is Selected //if (selIt->Value() && selItNext->Value())//selected //{ // float colorSel[]={1.0,0.0,0.6}; //for selected! // //current color for changing to a diferent color if selected // float currCol[4]; // glGetFloatv(GL_CURRENT_COLOR,currCol); // glColor3f(colorSel[0],colorSel[1],colorSel[2]);//red // glBegin (GL_LINES); // glVertex2f(p2d[0], p2d[1]); // glVertex2f(q2d[0], q2d[1]); // glEnd (); // glColor3f(currCol[0],currCol[1],currCol[2]);//the color before changing to select! //} //else //{ glBegin (GL_LINES); glVertex2f(p2d[0], p2d[1]); glVertex2f(q2d[0], q2d[1]); glEnd (); //} } ++it; ++selIt; j++; } //drawing the points PointSetGLMapper2D::Paint(renderer); } } diff --git a/Modules/MitkExt/Rendering/mitkMeshMapper2D.cpp b/Modules/MitkExt/Rendering/mitkMeshMapper2D.cpp index 17c010635e..4b29bdf907 100644 --- a/Modules/MitkExt/Rendering/mitkMeshMapper2D.cpp +++ b/Modules/MitkExt/Rendering/mitkMeshMapper2D.cpp @@ -1,476 +1,481 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkMeshMapper2D.h" #include "mitkMesh.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkLine.h" #include "mitkGL.h" #include #include const float selectedColor[]={1.0,0.0,0.6}; //for selected! mitk::MeshMapper2D::MeshMapper2D() { } mitk::MeshMapper2D::~MeshMapper2D() { } const mitk::Mesh *mitk::MeshMapper2D::GetInput(void) { - return static_cast ( GetData() ); + 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 ) { - if ( !this->IsVisible(renderer) ) return; + + 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 TimeSlicedGeometry of the input object const TimeSlicedGeometry* inputTimeGeometry = input->GetTimeSlicedGeometry(); if (( inputTimeGeometry == NULL ) || ( inputTimeGeometry->GetTimeSteps() == 0 ) ) { return; } // // get the world time // const Geometry2D* worldGeometry = renderer->GetCurrentWorldGeometry2D(); assert( worldGeometry != NULL ); ScalarType time = worldGeometry->GetTimeBounds()[ 0 ]; // // convert the world time in time steps of the input object // int timeStep=0; if ( time > ScalarTypeNumericTraits::NonpositiveMin() ) timeStep = inputTimeGeometry->MSToTimeStep( time ); if ( inputTimeGeometry->IsValidTime( timeStep ) == false ) { return; } mitk::Mesh::MeshType::Pointer itkMesh = input->GetMesh( timeStep ); if ( itkMesh.GetPointer() == NULL) { return; } mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert(displayGeometry.IsNotNull()); const PlaneGeometry* worldplanegeometry = dynamic_cast(renderer->GetCurrentWorldGeometry2D()); //apply color and opacity read from the PropertyList - ApplyProperties(renderer); + 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); displayGeometry->Project(p, projected_p); Vector3D diff=p-projected_p; if(diff.GetSquaredNorm()<4.0) { Point2D pt2d, tmp; displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, 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; glVertex2fv(&tmp[0]); tmp=pt2d+horz+vert; glVertex2fv(&tmp[0]); tmp=pt2d+horz-vert; glVertex2fv(&tmp[0]); tmp=pt2d-horz-vert; glVertex2fv(&tmp[0]); glEnd (); } break; case PTUNDEFINED: { //a diamond around the point glBegin (GL_LINE_LOOP); tmp=pt2d-horz; glVertex2fv(&tmp[0]); tmp=pt2d+vert; glVertex2fv(&tmp[0]); tmp=pt2d+horz; glVertex2fv(&tmp[0]); tmp=pt2d-vert; glVertex2fv(&tmp[0]); glEnd (); } break; default: break; }//switch //the actual point glBegin (GL_POINTS); tmp=pt2d; glVertex2fv(&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; glVertex2fv(&tmp[0]); tmp=pt2d+horz+vert; glVertex2fv(&tmp[0]); tmp=pt2d+horz-vert; glVertex2fv(&tmp[0]); tmp=pt2d-horz-vert; glVertex2fv(&tmp[0]); glEnd (); } case PTUNDEFINED: { //drawing crosses glBegin (GL_LINES); tmp=pt2d-horz; glVertex2fv(&tmp[0]); tmp=pt2d+horz; glVertex2fv(&tmp[0]); tmp=pt2d-vert; glVertex2fv(&tmp[0]); tmp=pt2d+vert; glVertex2fv(&tmp[0]); glEnd (); } default: { break; } }//switch }//else } ++it; ++dataIt; } //now connect the lines inbetween mitk::Mesh::PointType thisPoint; thisPoint.Fill(0); Point2D *firstOfCell = NULL; Point2D *lastPoint = NULL; 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); intersectionPoints.clear(); intersectionPoints.reserve(numOfPointsInCell); first = true; while(cellIdIt != cellIdEnd) { lastPoint3D = thisPoint; thisPoint = input->GetPoint(*cellIdIt); //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 Mesh::SelectedLinesIter 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); displayGeometry->Project(p, projected_p); Vector3D diff=p-projected_p; if(diff.GetSquaredNorm()<4.0) { Point2D pt2d, tmp; displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); if (lastPoint == NULL) { //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); glVertex2fv(&(*lastPoint)[0]); glVertex2fv(&pt2d[0]); glEnd (); } else //if not selected { glColor3f(unselectedColor[0],unselectedColor[1],unselectedColor[2]); //drawing crosses glBegin (GL_LINES); glVertex2fv(&(*lastPoint)[0]); glVertex2fv(&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!=NULL)) { 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 != NULL ) { lineSelected = false; Mesh::SelectedLinesType selectedLines = cellDataIt->Value().selectedLines; Mesh::SelectedLinesIter 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); glVertex2fv(&(*lastPoint)[0]); glVertex2fv(&(*firstOfCell)[0]); glEnd (); } else { glColor3f(unselectedColor[0],unselectedColor[1],unselectedColor[2]); glBegin (GL_LINES); glVertex2fv(&(*lastPoint)[0]); glVertex2fv(&(*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")) == NULL) 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); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, min2D); displayGeometry->WorldToDisplay(min2D, min2D); itk2vtk(max, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); displayGeometry->Project(p, projected_p); Vector3D diff=p-projected_p; if(diff.GetSquaredNorm()<4.0) { displayGeometry->Map(projected_p, max2D); displayGeometry->WorldToDisplay(max2D, 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!=NULL) { //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 } float p[2]; Point3D pt3d; Point2D pt2d; for ( it = intersectionPoints.begin( ); it != end; ++it ) { glBegin (GL_LINES); displayGeometry->Map(*it, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); p[0] = pt2d[0]; p[1] = pt2d[1]; glVertex2fv(p); ++it; displayGeometry->Map(*it, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); p[0] = pt2d[0]; p[1] = pt2d[1]; glVertex2fv(p); glEnd (); } if(it!=intersectionPoints.end()) { glBegin (GL_LINES); displayGeometry->Map(*it, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); p[0] = pt2d[0]; p[1] = pt2d[1]; glVertex2fv(p); p[0] = pt2d[0]; p[1] = pt2d[1]; glVertex2fv(p); glEnd (); } }//fill off-plane polygon part 2 }//if numOfPointsInCell>1 delete firstOfCell; delete lastPoint; lastPoint = NULL; firstOfCell = NULL; lastPointId = 0; ++cellIt; ++cellDataIt; } } } diff --git a/Modules/MitkExt/Rendering/mitkMeshMapper2D.h b/Modules/MitkExt/Rendering/mitkMeshMapper2D.h index 202c6bbbfe..df6ad8b4e6 100644 --- a/Modules/MitkExt/Rendering/mitkMeshMapper2D.h +++ b/Modules/MitkExt/Rendering/mitkMeshMapper2D.h @@ -1,58 +1,58 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKMESHMAPPER2D_H_HEADER_INCLUDED #define MITKMESHMAPPER2D_H_HEADER_INCLUDED #include "mitkCommon.h" #include "MitkExtExports.h" -#include "mitkGLMapper2D.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 MitkExt_EXPORT MeshMapper2D : public GLMapper2D +class MitkExt_EXPORT MeshMapper2D : public GLMapper { public: - mitkClassMacro(MeshMapper2D, Mapper2D); + mitkClassMacro(MeshMapper2D, GLMapper); itkNewMacro(Self); /** @brief Get the Mesh to map */ const mitk::Mesh *GetInput(void); virtual void Paint( mitk::BaseRenderer *renderer ); protected: MeshMapper2D(); virtual ~MeshMapper2D(); }; } // namespace mitk #endif /* MITKMESHMapper2D_H_HEADER_INCLUDED */ diff --git a/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.cpp b/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.cpp index f8b09edf76..b1cfd0a309 100644 --- a/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.cpp +++ b/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.cpp @@ -1,227 +1,228 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "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 ( GetData() ); + 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(NULL) { 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::GenerateData() + +void mitk::MeshVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer* renderer ) { + 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() == NULL) { m_PropAssembly->VisibilityOff(); return; } mitk::Mesh::PointsContainer::Iterator i; int j; float floatRgba[4] = {1.0f,1.0f,1.0f,1.0f}; vtkFloatingPointType 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, NULL); if (dynamic_cast(this->GetDataNode()->GetProperty("unselectedcolor")) != NULL) { 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++) { vtkSphereSource *sphere = vtkSphereSource::New(); sphere->SetRadius(pointSize); sphere->SetCenter(i.Value()[0],i.Value()[1],i.Value()[2]); m_Spheres->AddInput(sphere->GetOutput()); sphere->Delete(); } // setup mapper, actor and add to assembly m_SpheresMapper->SetInput(m_Spheres->GetOutput()); 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, NULL, m_Contour); #endif if(m_Contour->GetNumberOfCells()>0) { // setup mapper, actor and add to assembly m_ContourMapper->SetInput(m_Contour); bool wireframe=true; GetDataNode()->GetVisibility(wireframe, NULL, "wireframe"); if(wireframe) m_ContourActor->GetProperty()->SetRepresentationToWireframe(); else m_ContourActor->GetProperty()->SetRepresentationToSurface(); m_ContourActor->GetProperty()->SetColor(doubleRgba); m_PropAssembly->AddPart(m_ContourActor); } } -} - -void mitk::MeshVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer* renderer ) -{ SetVtkMapperImmediateModeRendering(m_ContourMapper); SetVtkMapperImmediateModeRendering(m_SpheresMapper); - if(IsVisible(renderer)==false) + 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/MitkExt/Rendering/mitkMeshVtkMapper3D.h b/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.h index 59a0af9697..3d1d18bd77 100644 --- a/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.h +++ b/Modules/MitkExt/Rendering/mitkMeshVtkMapper3D.h @@ -1,92 +1,90 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKMESHVTKMAPPER3D_H_HEADER_INCLUDED #define MITKMESHVTKMAPPER3D_H_HEADER_INCLUDED #include "mitkCommon.h" #include "MitkExtExports.h" -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include "mitkMesh.h" #include "mitkBaseRenderer.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 MitkExt_EXPORT MeshVtkMapper3D : public VtkMapper3D +class MitkExt_EXPORT MeshVtkMapper3D : public VtkMapper { public: - mitkClassMacro(MeshVtkMapper3D, VtkMapper3D); + mitkClassMacro(MeshVtkMapper3D, VtkMapper); itkNewMacro(Self); virtual const mitk::Mesh* GetInput(); virtual vtkProp* GetVtkProp(mitk::BaseRenderer *renderer); virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer); protected: MeshVtkMapper3D(); virtual ~MeshVtkMapper3D(); - virtual void GenerateData(); - virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); virtual void ResetMapper( BaseRenderer* renderer ); 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/MitkExt/Rendering/mitkSplineMapper2D.cpp b/Modules/MitkExt/Rendering/mitkSplineMapper2D.cpp index 81597d00f6..f81f3c4a35 100755 --- a/Modules/MitkExt/Rendering/mitkSplineMapper2D.cpp +++ b/Modules/MitkExt/Rendering/mitkSplineMapper2D.cpp @@ -1,189 +1,193 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSplineMapper2D.h" #include "mitkSplineVtkMapper3D.h" #include #include #include #include #include #include #include #include void mitk::SplineMapper2D::Paint ( mitk::BaseRenderer * renderer ) { Superclass::Paint ( renderer ); - if ( IsVisible ( renderer ) == false ) + + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible ) return; // // get the poly data of the splines in 3D // mitk::SplineVtkMapper3D::Pointer mapper3D = dynamic_cast ( this->GetDataNode()->GetMapper ( 2 ) ); if ( mapper3D.IsNull() ) { itkWarningMacro ( "Mapper used for 3D mapping is not a mitk::SplineVtkMapper3D!" ); return; } // // update the 3D spline, if the accoring mapper has not been updated yet // if ( mapper3D->GetLastUpdateTime() < GetDataNode()->GetData()->GetMTime() ) mapper3D->UpdateSpline(); vtkPolyData* spline3D = NULL; if ( mapper3D->SplinesAreAvailable() ) spline3D = mapper3D->GetSplinesPolyData(); else return; if ( spline3D == NULL ) { itkWarningMacro ( "3D spline is not available!" ); return; } // // get the transform associated with the data tree node // vtkLinearTransform* transform = this->GetDataNode()->GetVtkTransform(); if ( transform == NULL ) { itkWarningMacro("transfrom is NULL"); } // // get the plane geometry of the current renderer // mitk::Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); if ( worldGeometry.IsNull() ) { itkWarningMacro("worldGeometry is NULL!"); return; } PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast ( worldGeometry.GetPointer() ); if ( worldPlaneGeometry.IsNull() ) { itkWarningMacro("worldPlaneGeometry is NULL!"); return; } // // determine color of the spline // float color[3]; this->GetDataNode()->GetColor ( color, renderer ); // // iterate over the points // vtkPoints *vpoints = spline3D->GetPoints(); vtkCellArray *vlines = spline3D->GetLines(); if (vpoints == NULL) { itkWarningMacro("points are NULL!"); return; } if (vlines == NULL) { itkWarningMacro("lines are NULL!"); return; } mitk::Point3D currentPoint3D; mitk::Point2D currentPoint2D; vtkFloatingPointType currentPoint3DVtk[3]; vlines->InitTraversal(); int numberOfLines = vlines->GetNumberOfCells(); vtkFloatingPointType currentPointDistance; for ( int i = 0;i < numberOfLines; ++i ) { bool previousPointOnPlane = false; bool currentPointOnPlane = false; vtkIdType* cell ( NULL ); vtkIdType cellSize ( 0 ); vlines->GetNextCell ( cellSize, cell ); for ( int j = 0 ; j < cellSize; ++j ) { vpoints->GetPoint ( cell[j], currentPoint3DVtk ); // take transformation via vtktransform into account transform->TransformPoint ( currentPoint3DVtk, currentPoint3DVtk ); vtk2itk ( currentPoint3DVtk, currentPoint3D ); // check if the point has a distance to the plane // which is smaller than m_MaxProjectionDistance currentPointDistance = worldPlaneGeometry->DistanceFromPlane ( currentPoint3D ); if ( currentPointDistance < m_MaxProjectionDistance ) { currentPointOnPlane = true; //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map ( currentPoint3D, currentPoint2D ); //convert point (until now mm and in worldcoordinates) to display coordinates (units ) renderer->GetDisplayGeometry()->WorldToDisplay ( currentPoint2D, currentPoint2D ); } else currentPointOnPlane = false; // // check if we have to begin or end a GL_LINE // if ( ( previousPointOnPlane == false ) && ( currentPointOnPlane == true ) ) { glLineWidth ( m_LineWidth ); glColor3f ( color[0], color[1], color[2] ); glBegin ( GL_LINE_STRIP ); } else if ( ( previousPointOnPlane == true ) && ( currentPointOnPlane == false ) ) { glEnd (); glLineWidth ( 1.0 ); } // the current ponit is on the plane, add it as point to the // line segment if ( currentPointOnPlane == true ) { glVertex2f ( currentPoint2D[0], currentPoint2D[1] ); } previousPointOnPlane = currentPointOnPlane; } // the last point of the spline segment is on the plane, thus we have to // close the GL_LINE if ( previousPointOnPlane == true ) { glEnd (); glLineWidth ( 1.0 ); } previousPointOnPlane = false; } } void mitk::SplineMapper2D::ApplyProperties ( mitk::BaseRenderer* renderer ) { - Superclass::ApplyProperties ( renderer ); + ApplyColorAndOpacityProperties ( renderer ); } mitk::SplineMapper2D::SplineMapper2D() { m_MaxProjectionDistance = 1; m_ShowDistantLines = false ; m_LineWidth = 1; } mitk::SplineMapper2D::~SplineMapper2D() {} diff --git a/Modules/MitkExt/Rendering/mitkSplineMapper2D.h b/Modules/MitkExt/Rendering/mitkSplineMapper2D.h index 668ba0e99a..30c6d704fa 100755 --- a/Modules/MitkExt/Rendering/mitkSplineMapper2D.h +++ b/Modules/MitkExt/Rendering/mitkSplineMapper2D.h @@ -1,83 +1,83 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKSplineMapper2D_H_HEADER_INCLUDED #define MITKSplineMapper2D_H_HEADER_INCLUDED #include "mitkCommon.h" #include "MitkExtExports.h" -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" #include "mitkPointSetGLMapper2D.h" #include namespace mitk { class BaseRenderer; class PointSet; //##Documentation //## @brief OpenGL-based mapper to display a spline based on a mitk::PointSet in a 2D window. //## /** This mapper can actually more than just draw a number of points of a * mitk::PointSet. If you set the right properties of the mitk::DataNode, * which contains the point set, then this mapper will also draw lines * connecting the points, and calculate and display distances and angles * between adjacent points. Here is a complete list of boolean properties, * which might be of interest: * * - \b "show contour": Draw not only the points but also the connections between * them (default false) * - \b "line width": IntProperty which gives the width of the contour lines * - \b "show points": Wheter or not to draw the actual points (default true) * - \b "show distances": Wheter or not to calculate and print the distance * between adjacent points (default false) * - \b "show angles": Wheter or not to calculate and print the angle between * adjacent points (default false) * - \b "show distant lines": When true, the mapper will also draw contour * lines that are far away form the current slice (default true) * - \b "label": StringProperty with a label for this point set */ //## @ingroup Mapper class MitkExt_EXPORT SplineMapper2D : public PointSetGLMapper2D { public: mitkClassMacro ( SplineMapper2D, PointSetGLMapper2D ); itkNewMacro ( Self ); virtual void Paint ( mitk::BaseRenderer * renderer ); virtual void ApplyProperties ( mitk::BaseRenderer* renderer ); itkSetMacro ( MaxProjectionDistance, vtkFloatingPointType ); itkGetMacro ( MaxProjectionDistance, vtkFloatingPointType ); protected: SplineMapper2D(); virtual ~SplineMapper2D(); vtkFloatingPointType m_MaxProjectionDistance; }; } // namespace mitk #endif /* MITKSplineMapper2D_H_HEADER_INCLUDED */ diff --git a/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.cpp b/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.cpp index 07f55a227c..9c311a3227 100644 --- a/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.cpp +++ b/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.cpp @@ -1,236 +1,234 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSplineVtkMapper3D.h" #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::SplineVtkMapper3D::SplineVtkMapper3D() : m_SplinesAvailable (false), m_SplinesAddedToAssembly(false) { m_SplinesActor = vtkActor::New(); m_SplineAssembly = vtkPropAssembly::New(); m_SplineResolution = 500; } mitk::SplineVtkMapper3D::~SplineVtkMapper3D() { m_SplinesActor->Delete(); m_SplineAssembly->Delete(); } vtkProp* mitk::SplineVtkMapper3D::GetVtkProp(mitk::BaseRenderer * /*renderer*/) { return m_SplineAssembly; } void mitk::SplineVtkMapper3D::UpdateVtkTransform(mitk::BaseRenderer * /*renderer*/) { vtkLinearTransform * vtktransform = this->GetDataNode()->GetVtkTransform(this->GetTimestep()); m_SplinesActor->SetUserTransform(vtktransform); } -void -mitk::SplineVtkMapper3D::GenerateData() + +void mitk::SplineVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer* renderer ) { - Superclass::GenerateData(); // only update spline if UpdateSpline has not been called from // external, e.g. by the SplineMapper2D. But call it the first time when m_SplineUpdateTime = 0 and m_LastUpdateTime = 0. if ( m_SplineUpdateTime < m_LastUpdateTime || m_SplineUpdateTime == 0) { this->UpdateSpline(); - this->ApplyProperties(m_SplinesActor, NULL); + this->ApplyAllProperties(renderer, m_SplinesActor); } if ( m_SplinesAvailable ) { if ( ! m_SplinesAddedToAssembly ) { m_SplineAssembly->AddPart( m_SplinesActor ); m_SplinesAddedToAssembly = true; } } else { if ( m_SplinesAddedToAssembly ) { m_SplineAssembly->RemovePart( m_SplinesActor ); m_SplinesAddedToAssembly = false; } } -} + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); -void mitk::SplineVtkMapper3D::GenerateDataForRenderer( mitk::BaseRenderer* renderer ) -{ - if ( IsVisible( renderer ) == false ) + if(!visible) { m_SplinesActor->VisibilityOff(); m_SplineAssembly->VisibilityOff(); } else { m_SplinesActor->VisibilityOn(); m_SplineAssembly->VisibilityOn(); //remove the PointsAssembly if it was added in superclass. No need to display points and spline! if(m_SplineAssembly->GetParts()->IsItemPresent(m_PointsAssembly)) m_SplineAssembly->RemovePart(m_PointsAssembly); } //if the properties have been changed, then refresh the properties if ( (m_SplineUpdateTime < this->m_DataNode->GetPropertyList()->GetMTime() ) || (m_SplineUpdateTime < this->m_DataNode->GetPropertyList(renderer)->GetMTime() ) ) - this->ApplyProperties(m_SplinesActor, NULL); + this->ApplyAllProperties(renderer, m_SplinesActor); } -void mitk::SplineVtkMapper3D::ApplyProperties(vtkActor *actor, BaseRenderer *renderer) +void mitk::SplineVtkMapper3D::ApplyAllProperties(BaseRenderer *renderer, vtkActor *actor) { - Superclass::ApplyProperties(actor, renderer); + Superclass::ApplyColorAndOpacityProperties(renderer, actor); //vtk changed the type of rgba during releases. Due to that, the following convert is done vtkFloatingPointType rgba[ 4 ] = {1.0f, 1.0f, 1.0f, 1.0f};//white //getting the color from DataNode float temprgba[4]; this->GetDataNode()->GetColor( &temprgba[0], NULL ); //convert to rgba, what ever type it has! rgba[0] = temprgba[0]; rgba[1] = temprgba[1]; rgba[2] = temprgba[2]; rgba[3] = temprgba[3]; //finaly set the color inside the actor m_SplinesActor->GetProperty()->SetColor( rgba ); float lineWidth; if (dynamic_cast(this->GetDataNode()->GetProperty("line width")) == NULL) lineWidth = 1.0; else lineWidth = dynamic_cast(this->GetDataNode()->GetProperty("line width"))->GetValue(); m_SplinesActor->GetProperty()->SetLineWidth(lineWidth); m_SplineUpdateTime.Modified(); } bool mitk::SplineVtkMapper3D::SplinesAreAvailable() { return m_SplinesAvailable; } vtkPolyData* mitk::SplineVtkMapper3D::GetSplinesPolyData() { if ( m_SplinesAvailable ) return ( dynamic_cast( m_SplinesActor->GetMapper() ) )->GetInput(); else return NULL; } vtkActor* mitk::SplineVtkMapper3D::GetSplinesActor() { if ( m_SplinesAvailable ) return m_SplinesActor; else return vtkActor::New(); } unsigned long mitk::SplineVtkMapper3D::GetLastUpdateTime() const { return m_LastUpdateTime.GetMTime(); } void mitk::SplineVtkMapper3D::UpdateSpline() { mitk::PointSet::Pointer input = const_cast( this->GetInput( ) ); // input->Update();//already done in superclass // Number of points on the spline unsigned int numberOfOutputPoints = m_SplineResolution; unsigned int numberOfInputPoints = input->GetSize(); if ( numberOfInputPoints >= 2 ) { m_SplinesAvailable = true; vtkCardinalSpline* splineX = vtkCardinalSpline::New(); vtkCardinalSpline* splineY = vtkCardinalSpline::New(); vtkCardinalSpline* splineZ = vtkCardinalSpline::New(); unsigned int index = 0; mitk::PointSet::DataType::PointsContainer::Pointer pointsContainer = input->GetPointSet()->GetPoints(); for ( mitk::PointSet::DataType::PointsContainer::Iterator it = pointsContainer->Begin(); it != pointsContainer->End(); ++it, ++index ) //for ( unsigned int i = 0 ; i < numberOfInputPoints; ++i ) { mitk::PointSet::PointType point = it->Value(); splineX->AddPoint( index, point[ 0 ] ); splineY->AddPoint( index, point[ 1 ] ); splineZ->AddPoint( index, point[ 2 ] ); } vtkPoints* points = vtkPoints::New(); vtkPolyData* profileData = vtkPolyData::New(); // Interpolate x, y and z by using the three spline filters and // create new points double t = 0.0f; for ( unsigned int i = 0; i < numberOfOutputPoints; ++i ) { t = ( ( ( ( double ) numberOfInputPoints ) - 1.0f ) / ( ( ( double ) numberOfOutputPoints ) - 1.0f ) ) * ( ( double ) i ); points->InsertPoint( i, splineX->Evaluate( t ), splineY->Evaluate( t ), splineZ->Evaluate( t ) ) ; } // Create the polyline. vtkCellArray* lines = vtkCellArray::New(); lines->InsertNextCell( numberOfOutputPoints ); for ( unsigned int i = 0; i < numberOfOutputPoints; ++i ) lines->InsertCellPoint( i ); profileData->SetPoints( points ); profileData->SetLines( lines ); // Add thickness to the resulting line. //vtkTubeFilter* profileTubes = vtkTubeFilter::New(); //profileTubes->SetNumberOfSides(8); //profileTubes->SetInput(profileData); //profileTubes->SetRadius(.005); vtkPolyDataMapper* profileMapper = vtkPolyDataMapper::New(); profileMapper->SetInput( profileData ); m_SplinesActor->SetMapper( profileMapper ); } else { m_SplinesAvailable = false; } m_SplineUpdateTime.Modified(); } diff --git a/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.h b/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.h index 0a03a5a0fd..dd9a41691b 100644 --- a/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.h +++ b/Modules/MitkExt/Rendering/mitkSplineVtkMapper3D.h @@ -1,98 +1,96 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_SPLINE_VTK_MAPPER_3D__H #define _MITK_SPLINE_VTK_MAPPER_3D__H #include "mitkPointSetVtkMapper3D.h" #include "MitkExtExports.h" class vtkActor; class vtkAssembly; namespace mitk { //##Documentation //## @brief Vtk-based mapper for Splines //## //## properties looked for: //## "line width" = with of the spline //## @ingroup Mapper /************************************************************************/ /* * - \b "line width": (FloatProperty) line width of the spline */ /************************************************************************/ class MitkExt_EXPORT SplineVtkMapper3D : public PointSetVtkMapper3D { public: mitkClassMacro( SplineVtkMapper3D, PointSetVtkMapper3D ); itkNewMacro( Self ); virtual vtkProp* GetVtkProp(mitk::BaseRenderer *renderer); virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer); bool SplinesAreAvailable(); vtkPolyData* GetSplinesPolyData(); vtkActor* GetSplinesActor(); unsigned long GetLastUpdateTime() const; virtual void UpdateSpline(); itkSetMacro( SplineResolution, unsigned int ); itkGetMacro( SplineResolution, unsigned int ); protected: SplineVtkMapper3D(); virtual ~SplineVtkMapper3D(); - virtual void GenerateData(); - virtual void GenerateDataForRenderer(mitk::BaseRenderer * renderer); - virtual void ApplyProperties(vtkActor *actor, BaseRenderer *renderer); + virtual void ApplyAllProperties(BaseRenderer *renderer, vtkActor *actor); vtkActor* m_SplinesActor; vtkPropAssembly* m_SplineAssembly; bool m_SplinesAvailable; bool m_SplinesAddedToAssembly; unsigned int m_SplineResolution; itk::TimeStamp m_SplineUpdateTime; }; } //namespace mitk #endif diff --git a/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.cpp b/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.cpp index d67ae504ed..8ce7980bee 100644 --- a/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.cpp +++ b/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.cpp @@ -1,570 +1,567 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include "mitkUnstructuredGridMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkUnstructuredGrid.h" #include "mitkTransferFunction.h" #include "mitkTransferFunctionProperty.h" #include "mitkColorProperty.h" #include "mitkVtkScalarModeProperty.h" #include "mitkProperties.h" #include "mitkAbstractTransformGeometry.h" #include "mitkVtkMapper3D.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -void mitk::UnstructuredGridMapper2D::GenerateData() +void mitk::UnstructuredGridMapper2D::GenerateDataForRenderer( mitk::BaseRenderer* renderer ) { - mitk::DataNode::ConstPointer node = this->GetDataNode(); + + mitk::DataNode::ConstPointer node = this->GetDataNode(); if ( node.IsNull() ) return; - if (!node->GetProperty(m_ScalarMode, "scalar mode")) { m_ScalarMode = mitk::VtkScalarModeProperty::New(0); } if (!node->GetProperty(m_ScalarVisibility, "scalar visibility")) { m_ScalarVisibility = mitk::BoolProperty::New(true); } if (!node->GetProperty(m_Outline, "outline polygons")) { m_Outline = mitk::BoolProperty::New(false); } if (!node->GetProperty(m_Color, "color")) { m_Color = mitk::ColorProperty::New(1.0f, 1.0f, 1.0f); } if (!node->GetProperty(m_LineWidth, "line width")) { m_LineWidth = mitk::IntProperty::New(1); } -} - -void mitk::UnstructuredGridMapper2D::GenerateDataForRenderer( mitk::BaseRenderer* renderer ) -{ - mitk::BaseData::Pointer input = const_cast( this->GetData() ); + mitk::BaseData::Pointer input = const_cast( GetDataNode()->GetData() ); assert( input ); input->Update(); if (m_VtkPointSet) m_VtkPointSet->UnRegister(0); m_VtkPointSet = this->GetVtkPointSet(renderer); assert(m_VtkPointSet); m_VtkPointSet->Register(0); if (m_ScalarVisibility->GetValue()) { mitk::DataNode::ConstPointer node = this->GetDataNode(); mitk::TransferFunctionProperty::Pointer transferFuncProp; node->GetProperty(transferFuncProp, "TransferFunction", renderer); if (transferFuncProp.IsNotNull()) { mitk::TransferFunction::Pointer tf = transferFuncProp->GetValue(); if (m_ScalarsToColors) m_ScalarsToColors->UnRegister(0); m_ScalarsToColors = static_cast(tf->GetColorTransferFunction()); m_ScalarsToColors->Register(0); if (m_ScalarsToOpacity) m_ScalarsToOpacity->UnRegister(0); m_ScalarsToOpacity = tf->GetScalarOpacityFunction(); m_ScalarsToOpacity->Register(0); } else { if (m_ScalarsToColors) m_ScalarsToColors->UnRegister(0); m_ScalarsToColors = this->GetVtkLUT(renderer); assert(m_ScalarsToColors); m_ScalarsToColors->Register(0); float opacity; node->GetOpacity(opacity, renderer); if (m_ScalarsToOpacity) m_ScalarsToOpacity->UnRegister(0); m_ScalarsToOpacity = vtkPiecewiseFunction::New(); double range[2]; m_VtkPointSet->GetScalarRange(range); m_ScalarsToOpacity->AddSegment(range[0], opacity, range[1], opacity); } } } void mitk::UnstructuredGridMapper2D::Paint( mitk::BaseRenderer* renderer ) { - if ( IsVisible( renderer ) == false ) - return ; + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + if(!visible) return; vtkLinearTransform * vtktransform = GetDataNode()->GetVtkTransform(); vtkLinearTransform * inversetransform = vtktransform->GetLinearInverse(); Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); Point3D point; Vector3D normal; if(worldPlaneGeometry.IsNotNull()) { // set up vtkPlane according to worldGeometry point=worldPlaneGeometry->GetOrigin(); normal=worldPlaneGeometry->GetNormal(); normal.Normalize(); m_Plane->SetTransform((vtkAbstractTransform*)NULL); } else { //@FIXME: does not work correctly. Does m_Plane->SetTransform really transforms a "plane plane" into a "curved plane"? return; AbstractTransformGeometry::ConstPointer worldAbstractGeometry = dynamic_cast(renderer->GetCurrentWorldGeometry2D()); if(worldAbstractGeometry.IsNotNull()) { // set up vtkPlane according to worldGeometry point=const_cast(worldAbstractGeometry->GetParametricBoundingBox())->GetMinimum(); FillVector3D(normal, 0, 0, 1); m_Plane->SetTransform(worldAbstractGeometry->GetVtkAbstractTransform()->GetInverse()); } else return; } vtkFloatingPointType vp[ 3 ], vnormal[ 3 ]; vnl2vtk(point.Get_vnl_vector(), vp); vnl2vtk(normal.Get_vnl_vector(), vnormal); //normally, we would need to transform the surface and cut the transformed surface with the cutter. //This might be quite slow. Thus, the idea is, to perform an inverse transform of the plane instead. //@todo It probably does not work for scaling operations yet:scaling operations have to be //dealed with after the cut is performed by scaling the contour. inversetransform->TransformPoint( vp, vp ); inversetransform->TransformNormalAtPoint( vp, vnormal, vnormal ); m_Plane->SetOrigin( vp ); m_Plane->SetNormal( vnormal ); // set data into cutter m_Slicer->SetInput( m_VtkPointSet ); // m_Cutter->GenerateCutScalarsOff(); // m_Cutter->SetSortByToSortByCell(); // calculate the cut m_Slicer->Update(); // fetch geometry mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert( displayGeometry ); // float toGL=displayGeometry->GetSizeInDisplayUnits()[1]; //apply color and opacity read from the PropertyList - ApplyProperties( renderer ); + ApplyColorAndOpacityProperties( renderer ); // traverse the cut contour vtkPolyData * contour = m_Slicer->GetOutput(); vtkPoints *vpoints = contour->GetPoints(); vtkCellArray *vlines = contour->GetLines(); vtkCellArray *vpolys = contour->GetPolys(); vtkPointData *vpointdata = contour->GetPointData(); vtkDataArray* vscalars = vpointdata->GetScalars(); vtkCellData *vcelldata = contour->GetCellData(); vtkDataArray* vcellscalars = vcelldata->GetScalars(); const int numberOfLines = contour->GetNumberOfLines(); const int numberOfPolys = contour->GetNumberOfPolys(); const bool useCellData = m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_DEFAULT || m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_CELL_DATA; const bool usePointData = m_ScalarMode->GetVtkScalarMode() == VTK_SCALAR_MODE_USE_POINT_DATA; Point3D p; Point2D p2d; vlines->InitTraversal(); vpolys->InitTraversal(); mitk::Color outlineColor = m_Color->GetColor(); glLineWidth((float)m_LineWidth->GetValue()); for (int i = 0;i < numberOfLines;++i ) { vtkIdType *cell(0); vtkIdType cellSize(0); vlines->GetNextCell( cellSize, cell ); float rgba[4] = {outlineColor[0], outlineColor[1], outlineColor[2], 1.0f}; if (m_ScalarVisibility->GetValue() && vcellscalars) { if ( useCellData ) { // color each cell according to cell data double scalar = vcellscalars->GetComponent( i, 0 ); double rgb[3] = { 1.0f, 1.0f, 1.0f }; m_ScalarsToColors->GetColor(scalar, rgb); rgba[0] = (float)rgb[0]; rgba[1] = (float)rgb[1]; rgba[2] = (float)rgb[2]; rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar); } else if ( usePointData ) { double scalar = vscalars->GetComponent( i, 0 ); double rgb[3] = { 1.0f, 1.0f, 1.0f }; m_ScalarsToColors->GetColor(scalar, rgb); rgba[0] = (float)rgb[0]; rgba[1] = (float)rgb[1]; rgba[2] = (float)rgb[2]; rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar); } } glColor4fv( rgba ); glBegin ( GL_LINE_LOOP ); for ( int j = 0;j < cellSize;++j ) { vpoints->GetPoint( cell[ j ], vp ); //take transformation via vtktransform into account vtktransform->TransformPoint( vp, vp ); vtk2itk( vp, p ); //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map( p, p2d ); //convert point (until now mm and in worldcoordinates) to display coordinates (units ) displayGeometry->WorldToDisplay( p2d, p2d ); //convert display coordinates ( (0,0) is top-left ) in GL coordinates ( (0,0) is bottom-left ) //p2d[1]=toGL-p2d[1]; //add the current vertex to the line glVertex2f( p2d[0], p2d[1] ); } glEnd (); } bool polyOutline = m_Outline->GetValue(); bool scalarVisibility = m_ScalarVisibility->GetValue(); // cache the transformed points // a fixed size array is way faster than 'new' // slices through 3d cells usually do not generated // polygons with more than 6 vertices const int maxPolySize = 10; Point2D* cachedPoints = new Point2D[maxPolySize*numberOfPolys]; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // only draw polygons if there are cell scalars // or the outline property is set to true if (scalarVisibility && vcellscalars) { glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); for (int i = 0;i < numberOfPolys;++i ) { vtkIdType *cell(0); vtkIdType cellSize(0); vpolys->GetNextCell( cellSize, cell ); float rgba[4] = {1.0f, 1.0f, 1.0f, 0}; if (scalarVisibility && vcellscalars) { if ( useCellData ) { // color each cell according to cell data double scalar = vcellscalars->GetComponent( i+numberOfLines, 0 ); double rgb[3] = { 1.0f, 1.0f, 1.0f }; m_ScalarsToColors->GetColor(scalar, rgb); rgba[0] = (float)rgb[0]; rgba[1] = (float)rgb[1]; rgba[2] = (float)rgb[2]; rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar); } else if ( usePointData ) { double scalar = vscalars->GetComponent( i, 0 ); double rgb[3] = { 1.0f, 1.0f, 1.0f }; m_ScalarsToColors->GetColor(scalar, rgb); rgba[0] = (float)rgb[0]; rgba[1] = (float)rgb[1]; rgba[2] = (float)rgb[2]; rgba[3] = (float)m_ScalarsToOpacity->GetValue(scalar); } } glColor4fv( rgba ); glBegin( GL_POLYGON ); for (int j = 0; j < cellSize; ++j) { vpoints->GetPoint( cell[ j ], vp ); //take transformation via vtktransform into account vtktransform->TransformPoint( vp, vp ); vtk2itk( vp, p ); //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map( p, p2d ); //convert point (until now mm and in worldcoordinates) to display coordinates (units ) displayGeometry->WorldToDisplay( p2d, p2d ); //convert display coordinates ( (0,0) is top-left ) in GL coordinates ( (0,0) is bottom-left ) //p2d[1]=toGL-p2d[1]; cachedPoints[i*10+j][0] = p2d[0]; cachedPoints[i*10+j][1] = p2d[1]; //add the current vertex to the line glVertex2f( p2d[0], p2d[1] ); } glEnd(); } if (polyOutline) { vpolys->InitTraversal(); glColor4f(outlineColor[0], outlineColor[1], outlineColor[2], 1.0f); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); for (int i = 0;i < numberOfPolys;++i) { vtkIdType *cell(0); vtkIdType cellSize(0); vpolys->GetNextCell( cellSize, cell ); glBegin( GL_POLYGON ); //glPolygonOffset(1.0, 1.0); for (int j = 0; j < cellSize; ++j) { //add the current vertex to the line glVertex2f( cachedPoints[i*10+j][0], cachedPoints[i*10+j][1] ); } glEnd(); } } } glDisable(GL_BLEND); delete cachedPoints; } vtkAbstractMapper3D* mitk::UnstructuredGridMapper2D ::GetVtkAbstractMapper3D(mitk::BaseRenderer * renderer) { //MITK_INFO << "GETVTKABSTRACTMAPPER3D\n"; mitk::DataNode::ConstPointer node = this->GetDataNode(); if ( node.IsNull() ) return 0; - mitk::VtkMapper3D::Pointer mitkMapper = dynamic_cast< mitk::VtkMapper3D* > ( node->GetMapper( 2 ) ); + mitk::VtkMapper::Pointer mitkMapper = dynamic_cast< mitk::VtkMapper* > ( node->GetMapper( 2 ) ); if ( mitkMapper.IsNull() ) { return 0; } mitkMapper->Update(renderer); vtkAssembly* assembly = dynamic_cast(mitkMapper->GetVtkProp(renderer)); if (assembly) { vtkProp3DCollection* collection = assembly->GetParts(); collection->InitTraversal(); vtkProp3D* prop3d = 0; do { prop3d = collection->GetNextProp3D(); vtkActor* actor = dynamic_cast( prop3d ); if (actor) { return dynamic_cast( actor->GetMapper() ); } vtkVolume* volume = dynamic_cast( prop3d ); if (volume) { return dynamic_cast( volume->GetMapper() ); } } while (prop3d != collection->GetLastProp3D()); } else { vtkActor* actor = dynamic_cast( mitkMapper->GetVtkProp(renderer) ); if (actor) { return dynamic_cast( actor->GetMapper() ); } vtkVolume* volume = dynamic_cast( mitkMapper->GetVtkProp(renderer) ); if (volume) { return dynamic_cast( volume->GetMapper() ); } } return 0; } vtkPointSet* mitk::UnstructuredGridMapper2D ::GetVtkPointSet(mitk::BaseRenderer* renderer) { //MITK_INFO << "GETVTKPOINTSET\n"; vtkAbstractMapper3D * abstractMapper = GetVtkAbstractMapper3D(renderer); if ( abstractMapper == 0 ) { // try to get data from the node mitk::DataNode::ConstPointer node = this->GetDataNode(); if ( node.IsNull() ) return 0; mitk::BaseData::Pointer data = node->GetData(); mitk::UnstructuredGrid::Pointer grid = dynamic_cast(data.GetPointer()); if (!grid.IsNull()) return static_cast(grid->GetVtkUnstructuredGrid()); return 0; } else { vtkMapper* mapper = dynamic_cast(abstractMapper); if (mapper) { return dynamic_cast(mapper->GetInput()); } vtkAbstractVolumeMapper* volMapper = dynamic_cast(abstractMapper); if (volMapper) { return dynamic_cast(volMapper->GetDataSetInput()); } } return 0; } vtkScalarsToColors* mitk::UnstructuredGridMapper2D::GetVtkLUT(mitk::BaseRenderer* renderer) { //MITK_INFO << "GETVTKLUT\n"; vtkMapper * mapper = dynamic_cast(GetVtkAbstractMapper3D(renderer)); if (mapper) return mapper->GetLookupTable(); else { mitk::DataNode::ConstPointer node = this->GetDataNode(); if ( node.IsNull() ) return 0; - mitk::VtkMapper3D::Pointer mitkMapper = dynamic_cast< mitk::VtkMapper3D* > ( node->GetMapper( 2 ) ); + mitk::VtkMapper::Pointer mitkMapper = dynamic_cast< mitk::VtkMapper* > ( node->GetMapper( 2 ) ); if ( mitkMapper.IsNull() ) { //MITK_INFO << "mitkMapper is null\n"; return 0; } mitkMapper->Update(renderer); vtkVolume* volume = dynamic_cast( mitkMapper->GetVtkProp(renderer) ); if (volume) { //MITK_INFO << "found volume prop\n"; return static_cast(volume->GetProperty()->GetRGBTransferFunction()); } vtkAssembly* assembly = dynamic_cast(mitkMapper->GetVtkProp(renderer)); if (assembly) { //MITK_INFO << "found assembly prop\n"; mitk::TransferFunctionProperty::Pointer transferFuncProp; node->GetProperty(transferFuncProp, "TransferFunction", 0); if (transferFuncProp.IsNotNull()) { MITK_INFO << "return colortransferfunction\n"; return static_cast(transferFuncProp->GetValue()->GetColorTransferFunction()); } } return 0; } } bool mitk::UnstructuredGridMapper2D::IsConvertibleToVtkPointSet(mitk::BaseRenderer * renderer) { return ( GetVtkPointSet(renderer) != 0 ); } mitk::UnstructuredGridMapper2D::UnstructuredGridMapper2D() { m_Plane = vtkPlane::New(); m_Slicer = vtkPointSetSlicer::New(); m_Slicer->SetSlicePlane( m_Plane ); m_ScalarsToColors = 0; m_ScalarsToOpacity = 0; m_VtkPointSet = 0; //m_LUT = vtkLookupTable::New(); //m_LUT->SetTableRange( 0, 255 ); //m_LUT->SetNumberOfColors( 255 ); //m_LUT->SetRampToLinear (); //m_LUT->Build(); } mitk::UnstructuredGridMapper2D::~UnstructuredGridMapper2D() { m_Slicer->Delete(); m_Plane->Delete(); if (m_ScalarsToOpacity != 0) m_ScalarsToOpacity->UnRegister(0); if (m_ScalarsToColors != 0) m_ScalarsToColors->UnRegister(0); if (m_VtkPointSet != 0) m_VtkPointSet->UnRegister(0); } diff --git a/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.h b/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.h index 83c4b45e78..6e8dd546b3 100644 --- a/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.h +++ b/Modules/MitkExt/Rendering/mitkUnstructuredGridMapper2D.h @@ -1,112 +1,111 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MitkPointSetSliceLMapper2D_H #define MitkPointSetSliceLMapper2D_H #include "mitkCommon.h" #include "MitkExtExports.h" -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" #include "mitkTransferFunction.h" #include "mitkProperties.h" #include "mitkColorProperty.h" #include "mitkVtkScalarModeProperty.h" class vtkPointSetSlicer; class vtkPlane; class vtkLookupTable; class vtkPointSet; class vtkScalarsToColors; class vtkPiecewiseFunction; class vtkAbstractMapper3D; namespace mitk { class BaseRenderer; /** * @brief OpenGL-based mapper to display a 2d cut through a poly data * OpenGL-based mapper to display a 2D cut through a poly data. The result is * normally a line. This class can be added to any data object, which is * rendered in 3D via a vtkPolyData. */ -class MitkExt_EXPORT UnstructuredGridMapper2D : public GLMapper2D +class MitkExt_EXPORT UnstructuredGridMapper2D : public GLMapper { public: - mitkClassMacro( UnstructuredGridMapper2D, GLMapper2D ); + mitkClassMacro( UnstructuredGridMapper2D, GLMapper ); itkNewMacro( Self ); /** * Renders a cut through a pointset by cutting trough the n-cells, * producing (n-1)-cells. * @param renderer the render to render in. */ virtual void Paint( mitk::BaseRenderer* renderer ); protected: UnstructuredGridMapper2D(); virtual ~UnstructuredGridMapper2D(); - virtual void GenerateData(); virtual void GenerateDataForRenderer(BaseRenderer*); /** * Determines, if the associated BaseData is mapped three-dimensionally (mapper-slot id 2) * with a class convertable to vtkAbstractMapper3D(). * @returns NULL if it is not convertable or the appropriate Mapper otherwise */ virtual vtkAbstractMapper3D* GetVtkAbstractMapper3D(BaseRenderer* renderer); /** * Determines the pointset object to be cut. * returns the pointset if possible, otherwise NULL. */ virtual vtkPointSet* GetVtkPointSet(BaseRenderer* renderer ); /** * Determines the LookupTable used by the associated vtkMapper. * returns the LUT if possible, otherwise NULL. */ virtual vtkScalarsToColors* GetVtkLUT(BaseRenderer* renderer ); /** * Checks if this mapper can be used to generate cuts through the associated * base data. * @return true if yes or false if not. */ virtual bool IsConvertibleToVtkPointSet(BaseRenderer* renderer); vtkPlane* m_Plane; vtkPointSetSlicer* m_Slicer; vtkPointSet* m_VtkPointSet; vtkScalarsToColors* m_ScalarsToColors; vtkPiecewiseFunction* m_ScalarsToOpacity; mitk::ColorProperty::Pointer m_Color; mitk::IntProperty::Pointer m_LineWidth; mitk::BoolProperty::Pointer m_Outline; mitk::BoolProperty::Pointer m_ScalarVisibility; mitk::VtkScalarModeProperty::Pointer m_ScalarMode; }; } // namespace mitk #endif /* MitkPointSetSliceLMapper2D_H */ diff --git a/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.cpp b/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.cpp index fecc620e54..1a955caeb7 100644 --- a/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.cpp +++ b/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.cpp @@ -1,416 +1,416 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkUnstructuredGridVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkTransferFunctionProperty.h" #include "mitkColorProperty.h" //#include "mitkLookupTableProperty.h" #include "mitkGridRepresentationProperty.h" #include "mitkGridVolumeMapperProperty.h" #include "mitkVtkInterpolationProperty.h" #include "mitkVtkScalarModeProperty.h" #include "mitkDataStorage.h" #include "mitkSurfaceVtkMapper3D.h" #include #include #include #include #include const mitk::UnstructuredGrid* mitk::UnstructuredGridVtkMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } mitk::UnstructuredGridVtkMapper3D::UnstructuredGridVtkMapper3D() { m_VtkTriangleFilter = vtkDataSetTriangleFilter::New(); m_Assembly = vtkAssembly::New(); m_Volume = vtkVolume::New(); m_Actor = vtkActor::New(); m_ActorWireframe = vtkActor::New(); m_VtkDataSetMapper = vtkUnstructuredGridMapper::New(); m_VtkDataSetMapper->SetResolveCoincidentTopologyToPolygonOffset(); m_VtkDataSetMapper->SetResolveCoincidentTopologyPolygonOffsetParameters(0,1); m_Actor->SetMapper(m_VtkDataSetMapper); m_VtkDataSetMapper2 = vtkUnstructuredGridMapper::New(); m_VtkDataSetMapper2->SetResolveCoincidentTopologyToPolygonOffset(); m_VtkDataSetMapper2->SetResolveCoincidentTopologyPolygonOffsetParameters(1,1); m_ActorWireframe->SetMapper(m_VtkDataSetMapper2); m_ActorWireframe->GetProperty()->SetRepresentationToWireframe(); m_Assembly->AddPart(m_Actor); m_Assembly->AddPart(m_ActorWireframe); m_Assembly->AddPart(m_Volume); m_VtkVolumeRayCastMapper = 0; m_VtkPTMapper = 0; m_VtkVolumeZSweepMapper = 0; //m_GenerateNormals = false; } mitk::UnstructuredGridVtkMapper3D::~UnstructuredGridVtkMapper3D() { if (m_VtkTriangleFilter != 0) m_VtkTriangleFilter->Delete(); if (m_VtkVolumeRayCastMapper != 0) m_VtkVolumeRayCastMapper->Delete(); if (m_VtkVolumeZSweepMapper != 0) m_VtkVolumeZSweepMapper->Delete(); if (m_VtkPTMapper != 0) m_VtkPTMapper->Delete(); if (m_VtkDataSetMapper != 0) m_VtkDataSetMapper->Delete(); if (m_VtkDataSetMapper2 != 0) m_VtkDataSetMapper2->Delete(); if (m_Assembly != 0) m_Assembly->Delete(); if (m_Actor != 0) m_Actor->Delete(); if (m_ActorWireframe != 0) m_ActorWireframe->Delete(); if (m_Volume != 0) m_Volume->Delete(); } vtkProp* mitk::UnstructuredGridVtkMapper3D::GetVtkProp(mitk::BaseRenderer* /*renderer*/) { return m_Assembly; } -void mitk::UnstructuredGridVtkMapper3D::GenerateData() + +void mitk::UnstructuredGridVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) { + m_Assembly->VisibilityOn(); m_ActorWireframe->GetProperty()->SetAmbient(1.0); m_ActorWireframe->GetProperty()->SetDiffuse(0.0); m_ActorWireframe->GetProperty()->SetSpecular(0.0); mitk::DataNode::ConstPointer node = this->GetDataNode(); mitk::TransferFunctionProperty::Pointer transferFuncProp; if (node->GetProperty(transferFuncProp, "TransferFunction")) { mitk::TransferFunction::Pointer transferFunction = transferFuncProp->GetValue(); if (transferFunction->GetColorTransferFunction()->GetSize() < 2) { mitk::UnstructuredGrid::Pointer input = const_cast< mitk::UnstructuredGrid* >(this->GetInput()); if (input.IsNull()) return; vtkUnstructuredGrid * grid = input->GetVtkUnstructuredGrid(this->GetTimestep()); if (grid == 0) return; double* scalarRange = grid->GetScalarRange(); vtkColorTransferFunction* colorFunc = transferFunction->GetColorTransferFunction(); colorFunc->RemoveAllPoints(); colorFunc->AddRGBPoint(scalarRange[0], 1, 0, 0); colorFunc->AddRGBPoint((scalarRange[0] + scalarRange[1])/2.0, 0, 1, 0); colorFunc->AddRGBPoint(scalarRange[1], 0, 0, 1); } } -} -void mitk::UnstructuredGridVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) -{ + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); - if(!IsVisible(renderer)) + if(!visible) { m_Assembly->VisibilityOff(); return; } // // get the TimeSlicedGeometry of the input object // mitk::UnstructuredGrid::Pointer input = const_cast< mitk::UnstructuredGrid* >( this->GetInput() ); // // set the input-object at time t for the mapper // vtkUnstructuredGrid * grid = input->GetVtkUnstructuredGrid( this->GetTimestep() ); if(grid == 0) { m_Assembly->VisibilityOff(); return; } m_Assembly->VisibilityOn(); m_VtkTriangleFilter->SetInput(grid); m_VtkDataSetMapper->SetInput(grid); m_VtkDataSetMapper2->SetInput(grid); - mitk::DataNode::ConstPointer node = this->GetDataNode(); bool clip = false; node->GetBoolProperty("enable clipping", clip); mitk::DataNode::Pointer bbNode = renderer->GetDataStorage()->GetNamedDerivedNode("Clipping Bounding Object", node); if (clip && bbNode.IsNotNull()) { m_VtkDataSetMapper->SetBoundingObject(dynamic_cast(bbNode->GetData())); m_VtkDataSetMapper2->SetBoundingObject(dynamic_cast(bbNode->GetData())); } else { m_VtkDataSetMapper->SetBoundingObject(0); m_VtkDataSetMapper2->SetBoundingObject(0); } // // apply properties read from the PropertyList // ApplyProperties(0, renderer); } void mitk::UnstructuredGridVtkMapper3D::ResetMapper( BaseRenderer* /*renderer*/ ) { m_Assembly->VisibilityOff(); } void mitk::UnstructuredGridVtkMapper3D::ApplyProperties(vtkActor* /*actor*/, mitk::BaseRenderer* renderer) { mitk::DataNode::Pointer node = this->GetDataNode(); - Superclass::ApplyProperties(m_Actor, renderer); - Superclass::ApplyProperties(m_ActorWireframe, renderer); + ApplyColorAndOpacityProperties(renderer, m_Actor); + ApplyColorAndOpacityProperties(renderer, m_ActorWireframe); vtkVolumeProperty* volProp = m_Volume->GetProperty(); vtkProperty* property = m_Actor->GetProperty(); vtkProperty* wireframeProp = m_ActorWireframe->GetProperty(); mitk::SurfaceVtkMapper3D::ApplyMitkPropertiesToVtkProperty(node,property,renderer); mitk::SurfaceVtkMapper3D::ApplyMitkPropertiesToVtkProperty(node,wireframeProp,renderer); mitk::TransferFunctionProperty::Pointer transferFuncProp; if (node->GetProperty(transferFuncProp, "TransferFunction", renderer)) { mitk::TransferFunction::Pointer transferFunction = transferFuncProp->GetValue(); volProp->SetColor(transferFunction->GetColorTransferFunction()); volProp->SetScalarOpacity(transferFunction->GetScalarOpacityFunction()); volProp->SetGradientOpacity(transferFunction->GetGradientOpacityFunction()); m_VtkDataSetMapper->SetLookupTable(transferFunction->GetColorTransferFunction()); m_VtkDataSetMapper2->SetLookupTable(transferFunction->GetColorTransferFunction()); } bool isVolumeRenderingOn = false; node->GetBoolProperty("volumerendering", isVolumeRenderingOn, renderer); if (isVolumeRenderingOn) { m_Assembly->RemovePart(m_Actor); m_Assembly->RemovePart(m_ActorWireframe); m_Assembly->AddPart(m_Volume); mitk::GridVolumeMapperProperty::Pointer mapperProp; if (node->GetProperty(mapperProp, "volumerendering.mapper", renderer)) { mitk::GridVolumeMapperProperty::IdType type = mapperProp->GetValueAsId(); switch (type) { case mitk::GridVolumeMapperProperty::RAYCAST: if (m_VtkVolumeRayCastMapper == 0) { m_VtkVolumeRayCastMapper = vtkUnstructuredGridVolumeRayCastMapper::New(); m_VtkVolumeRayCastMapper->SetInput(m_VtkTriangleFilter->GetOutput()); } m_Volume->SetMapper(m_VtkVolumeRayCastMapper); break; case mitk::GridVolumeMapperProperty::PT: if (m_VtkPTMapper == 0) { m_VtkPTMapper = vtkProjectedTetrahedraMapper::New(); m_VtkPTMapper->SetInputConnection(m_VtkTriangleFilter->GetOutputPort()); } m_Volume->SetMapper(m_VtkPTMapper); break; case mitk::GridVolumeMapperProperty::ZSWEEP: if (m_VtkVolumeZSweepMapper == 0) { m_VtkVolumeZSweepMapper = vtkUnstructuredGridVolumeZSweepMapper::New(); m_VtkVolumeZSweepMapper->SetInputConnection(m_VtkTriangleFilter->GetOutputPort()); } m_Volume->SetMapper(m_VtkVolumeZSweepMapper); break; } } } else { m_Assembly->RemovePart(m_Volume); m_Assembly->AddPart(m_Actor); m_Assembly->RemovePart(m_ActorWireframe); mitk::GridRepresentationProperty::Pointer gridRepProp; if (node->GetProperty(gridRepProp, "grid representation", renderer)) { mitk::GridRepresentationProperty::IdType type = gridRepProp->GetValueAsId(); switch (type) { case mitk::GridRepresentationProperty::POINTS: property->SetRepresentationToPoints(); break; case mitk::GridRepresentationProperty::WIREFRAME: property->SetRepresentationToWireframe(); break; case mitk::GridRepresentationProperty::SURFACE: property->SetRepresentationToSurface(); break; } // if (type == mitk::GridRepresentationProperty::WIREFRAME_SURFACE) // { // m_Assembly->AddPart(m_ActorWireframe); // } } } // mitk::LevelWindow levelWindow; // if(node->GetLevelWindow(levelWindow, renderer, "levelWindow")) // { // m_VtkVolumeRayCastMapper->SetScalarRange(levelWindow.GetMin(),levelWindow.GetMax()); // } // else // if(node->GetLevelWindow(levelWindow, renderer)) // { // m_VtkVolumeRayCastMapper->SetScalarRange(levelWindow.GetMin(),levelWindow.GetMax()); // } // // mitk::VtkRepresentationProperty* representationProperty; // node->GetProperty(representationProperty, "material.representation", renderer); // if ( representationProperty != NULL ) // m_Volume->GetProperty()->SetRepresentation( representationProperty->GetVtkRepresentation() ); // // mitk::VtkInterpolationProperty* interpolationProperty; // node->GetProperty(interpolationProperty, "material.interpolation", renderer); // if ( interpolationProperty != NULL ) // m_Volume->GetProperty()->SetInterpolation( interpolationProperty->GetVtkInterpolation() ); // mitk::VtkScalarModeProperty* scalarMode = 0; if(node->GetProperty(scalarMode, "scalar mode", renderer)) { if (m_VtkVolumeRayCastMapper) m_VtkVolumeRayCastMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); if (m_VtkPTMapper) m_VtkPTMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); if (m_VtkVolumeZSweepMapper) m_VtkVolumeZSweepMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); m_VtkDataSetMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); m_VtkDataSetMapper2->SetScalarMode(scalarMode->GetVtkScalarMode()); } else { if (m_VtkVolumeRayCastMapper) m_VtkVolumeRayCastMapper->SetScalarModeToDefault(); if (m_VtkPTMapper) m_VtkPTMapper->SetScalarModeToDefault(); if (m_VtkVolumeZSweepMapper) m_VtkVolumeZSweepMapper->SetScalarModeToDefault(); m_VtkDataSetMapper->SetScalarModeToDefault(); m_VtkDataSetMapper2->SetScalarModeToDefault(); } bool scalarVisibility = true; node->GetBoolProperty("scalar visibility", scalarVisibility, renderer); m_VtkDataSetMapper->SetScalarVisibility(scalarVisibility ? 1 : 0); m_VtkDataSetMapper2->SetScalarVisibility(scalarVisibility ? 1 : 0); // double scalarRangeLower = std::numeric_limits::min(); // double scalarRangeUpper = std::numeric_limits::max(); // mitk::DoubleProperty* lowerRange = 0; // if (node->GetProperty(lowerRange, "scalar range min", renderer)) // { // scalarRangeLower = lowerRange->GetValue(); // } // mitk::DoubleProperty* upperRange = 0; // if (node->GetProperty(upperRange, "scalar range max", renderer)) // { // scalarRangeUpper = upperRange->GetValue(); // } // m_VtkDataSetMapper->SetScalarRange(scalarRangeLower, scalarRangeUpper); // m_VtkDataSetMapper2->SetScalarRange(scalarRangeLower, scalarRangeUpper); // bool colorMode = false; // node->GetBoolProperty("color mode", colorMode); // m_VtkVolumeRayCastMapper->SetColorMode( (colorMode ? 1 : 0) ); // float scalarsMin = 0; // if (dynamic_cast(node->GetProperty("ScalarsRangeMinimum").GetPointer()) != NULL) // scalarsMin = dynamic_cast(node->GetProperty("ScalarsRangeMinimum").GetPointer())->GetValue(); // float scalarsMax = 1.0; // if (dynamic_cast(node->GetProperty("ScalarsRangeMaximum").GetPointer()) != NULL) // scalarsMax = dynamic_cast(node->GetProperty("ScalarsRangeMaximum").GetPointer())->GetValue(); // m_VtkVolumeRayCastMapper->SetScalarRange(scalarsMin,scalarsMax); } void mitk::UnstructuredGridVtkMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { SurfaceVtkMapper3D::SetDefaultPropertiesForVtkProperty(node, renderer, overwrite); node->AddProperty("grid representation", GridRepresentationProperty::New(), renderer, overwrite); node->AddProperty("volumerendering", BoolProperty::New(false), renderer, overwrite); node->AddProperty("volumerendering.mapper", GridVolumeMapperProperty::New(), renderer, overwrite); node->AddProperty("scalar mode", VtkScalarModeProperty::New(0), renderer, overwrite); node->AddProperty("scalar visibility", BoolProperty::New(true), renderer, overwrite); //node->AddProperty("scalar range min", DoubleProperty::New(std::numeric_limits::min()), renderer, overwrite); //node->AddProperty("scalar range max", DoubleProperty::New(std::numeric_limits::max()), renderer, overwrite); node->AddProperty("outline polygons", BoolProperty::New(false), renderer, overwrite); node->AddProperty("color", ColorProperty::New(1.0f, 1.0f, 1.0f), renderer, overwrite); node->AddProperty("line width", IntProperty::New(1), renderer, overwrite); if(overwrite || node->GetProperty("TransferFunction", renderer) == 0) { // add a default transfer function mitk::TransferFunction::Pointer tf = mitk::TransferFunction::New(); //tf->GetColorTransferFunction()->RemoveAllPoints(); node->SetProperty ("TransferFunction", mitk::TransferFunctionProperty::New(tf.GetPointer())); } Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.h b/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.h index 37e3828e52..52f208b015 100644 --- a/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.h +++ b/Modules/MitkExt/Rendering/mitkUnstructuredGridVtkMapper3D.h @@ -1,91 +1,90 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_UNSTRUCTURED_GRID_VTK_MAPPER_3D_H_ #define _MITK_UNSTRUCTURED_GRID_VTK_MAPPER_3D_H_ #include "mitkCommon.h" #include "MitkExtExports.h" -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include "mitkUnstructuredGrid.h" #include "mitkBaseRenderer.h" #include #include #include #include #include "vtkUnstructuredGridMapper.h" #include #include #include namespace mitk { //##Documentation //## @brief Vtk-based mapper for UnstructuredGrid //## //## @ingroup Mapper -class MitkExt_EXPORT UnstructuredGridVtkMapper3D : public VtkMapper3D +class MitkExt_EXPORT UnstructuredGridVtkMapper3D : public VtkMapper { public: - mitkClassMacro(UnstructuredGridVtkMapper3D, VtkMapper3D); + mitkClassMacro(UnstructuredGridVtkMapper3D, VtkMapper); itkNewMacro(Self); virtual const mitk::UnstructuredGrid* GetInput(); virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); void ApplyProperties(vtkActor* /*actor*/, mitk::BaseRenderer* renderer); protected: UnstructuredGridVtkMapper3D(); virtual ~UnstructuredGridVtkMapper3D(); - virtual void GenerateData(); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); virtual void ResetMapper( BaseRenderer* /*renderer*/ ); void SetProperties(mitk::BaseRenderer* renderer); vtkAssembly* m_Assembly; vtkActor* m_Actor; vtkActor* m_ActorWireframe; vtkVolume* m_Volume; vtkDataSetTriangleFilter* m_VtkTriangleFilter; vtkUnstructuredGridMapper* m_VtkDataSetMapper; vtkUnstructuredGridMapper* m_VtkDataSetMapper2; vtkUnstructuredGridVolumeRayCastMapper* m_VtkVolumeRayCastMapper; vtkProjectedTetrahedraMapper* m_VtkPTMapper; vtkUnstructuredGridVolumeZSweepMapper* m_VtkVolumeZSweepMapper; }; } // namespace mitk #endif /* _MITK_UNSTRUCTURED_GRID_VTK_MAPPER_3D_H_ */ diff --git a/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.cpp b/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.cpp index 9570c948e0..e4764abbd4 100644 --- a/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.cpp +++ b/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.cpp @@ -1,534 +1,538 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkVectorImageMapper2D.h" //vtk related includes #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 #include #include #include #include #include #include #include //mitk related includes #include "mitkGL.h" #include "mitkBaseRenderer.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkAbstractTransformGeometry.h" #include const mitk::Image * mitk::VectorImageMapper2D::GetInput( void ) { if ( m_Image.IsNotNull() ) return m_Image; else - return dynamic_cast( this->GetData() ); + return dynamic_cast( GetDataNode()->GetData() ); } void mitk::VectorImageMapper2D::Paint( mitk::BaseRenderer * renderer ) { //std::cout << "2d vector mapping..." << std::endl; - if ( IsVisible( renderer ) == false ) + + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible ) return ; mitk::Image::Pointer input = const_cast( this->GetInput() ); if ( input.IsNull() ) return ; mitk::PlaneGeometry::Pointer worldPlaneGeometry2D = dynamic_cast< mitk::PlaneGeometry*>( const_cast( renderer->GetCurrentWorldGeometry2D() ) ); assert( worldPlaneGeometry2D.IsNotNull() ); vtkImageData* vtkImage = input->GetVtkImageData( this->GetCurrentTimeStep( input, renderer ) ); // // set up the cutter orientation according to the current geometry of // the renderers plane // Point3D point; Vector3D normal; Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); PlaneGeometry::ConstPointer worldPlaneGeometry = dynamic_cast( worldGeometry.GetPointer() ); if ( worldPlaneGeometry.IsNotNull() ) { // set up vtkPlane according to worldGeometry point = worldPlaneGeometry->GetOrigin(); normal = worldPlaneGeometry->GetNormal(); normal.Normalize(); m_Plane->SetTransform( (vtkAbstractTransform*)NULL ); } else { itkWarningMacro( << "worldPlaneGeometry is NULL!" ); return ; } vtkFloatingPointType vp[ 3 ], vp_slice[ 3 ], vnormal[ 3 ]; vnl2vtk( point.Get_vnl_vector(), vp ); vnl2vtk( normal.Get_vnl_vector(), vnormal ); //std::cout << "Origin: " << vp[0] <<" "<< vp[1] <<" "<< vp[2] << std::endl; //std::cout << "Normal: " << vnormal[0] <<" "<< vnormal[1] <<" "<< vnormal[2] << std::endl; //normally, we would need to transform the surface and cut the transformed surface with the cutter. //This might be quite slow. Thus, the idea is, to perform an inverse transform of the plane instead. //@todo It probably does not work for scaling operations yet:scaling operations have to be //dealed with after the cut is performed by scaling the contour. vtkLinearTransform * vtktransform = GetDataNode() ->GetVtkTransform(); vtkTransform* world2vtk = vtkTransform::New(); world2vtk->Identity(); world2vtk->Concatenate(vtktransform->GetLinearInverse()); double myscale[3]; world2vtk->GetScale(myscale); world2vtk->PostMultiply(); world2vtk->Scale(1/myscale[0],1/myscale[1],1/myscale[2]); world2vtk->TransformPoint( vp, vp ); world2vtk->TransformNormalAtPoint( vp, vnormal, vnormal ); world2vtk->Delete(); // vtk works in axis align coords // thus the normal also must be axis align, since // we do not allow arbitrary cutting through volume // // vnormal should already be axis align, but in order // to get rid of precision effects, we set the two smaller // components to zero here int dims[3]; vtkImage->GetDimensions(dims); double spac[3]; vtkImage->GetSpacing(spac); vp_slice[0] = vp[0]; vp_slice[1] = vp[1]; vp_slice[2] = vp[2]; if(fabs(vnormal[0]) > fabs(vnormal[1]) && fabs(vnormal[0]) > fabs(vnormal[2]) ) { if(fabs(vp_slice[0]/spac[0]) < 0.4) vp_slice[0] = 0.4*spac[0]; if(fabs(vp_slice[0]/spac[0]) > (dims[0]-1)-0.4) vp_slice[0] = ((dims[0]-1)-0.4)*spac[0]; vnormal[1] = 0; vnormal[2] = 0; } if(fabs(vnormal[1]) > fabs(vnormal[0]) && fabs(vnormal[1]) > fabs(vnormal[2]) ) { if(fabs(vp_slice[1]/spac[1]) < 0.4) vp_slice[1] = 0.4*spac[1]; if(fabs(vp_slice[1]/spac[1]) > (dims[1]-1)-0.4) vp_slice[1] = ((dims[1]-1)-0.4)*spac[1]; vnormal[0] = 0; vnormal[2] = 0; } if(fabs(vnormal[2]) > fabs(vnormal[1]) && fabs(vnormal[2]) > fabs(vnormal[0]) ) { if(fabs(vp_slice[2]/spac[2]) < 0.4) vp_slice[2] = 0.4*spac[2]; if(fabs(vp_slice[2]/spac[2]) > (dims[2]-1)-0.4) vp_slice[2] = ((dims[2]-1)-0.4)*spac[2]; vnormal[0] = 0; vnormal[1] = 0; } m_Plane->SetOrigin( vp_slice ); m_Plane->SetNormal( vnormal ); vtkPolyData* cuttedPlane; if(!( (dims[0] == 1 && vnormal[0] != 0) || (dims[1] == 1 && vnormal[1] != 0) || (dims[2] == 1 && vnormal[2] != 0) )) { m_Cutter->SetCutFunction( m_Plane ); m_Cutter->SetInput( vtkImage ); m_Cutter->GenerateCutScalarsOff();//! m_Cutter->Update(); cuttedPlane = m_Cutter->GetOutput(); } else { // cutting of a 2D-Volume does not work, // so we have to build up our own polydata object cuttedPlane = vtkPolyData::New(); vtkPoints* points = vtkPoints::New(); points->SetNumberOfPoints(vtkImage->GetNumberOfPoints()); for(int i=0; iGetNumberOfPoints(); i++) points->SetPoint(i, vtkImage->GetPoint(i)); cuttedPlane->SetPoints(points); vtkFloatArray* pointdata = vtkFloatArray::New(); int comps = vtkImage->GetPointData()->GetScalars()->GetNumberOfComponents(); pointdata->SetNumberOfComponents(comps); int tuples = vtkImage->GetPointData()->GetScalars()->GetNumberOfTuples(); pointdata->SetNumberOfTuples(tuples); for(int i=0; iSetTuple(i,vtkImage->GetPointData()->GetScalars()->GetTuple(i)); pointdata->SetName( "vector" ); cuttedPlane->GetPointData()->AddArray(pointdata); } if ( cuttedPlane->GetNumberOfPoints() != 0) { // // make sure, that we have point data with more than 1 component (as vectors) // vtkPointData * pointData = cuttedPlane->GetPointData(); if ( pointData == NULL ) { itkWarningMacro( << "no point data associated with cutters result!" ); return ; } if ( pointData->GetNumberOfArrays() == 0 ) { itkWarningMacro( << "point data returned by cutter doesn't have any arrays associated!" ); return ; } else if ( pointData->GetArray(0)->GetNumberOfComponents() <= 1) { itkWarningMacro( << "number of components <= 1!" ); return; } else if ( pointData->GetArrayName( 0 ) == NULL ) { pointData->GetArray( 0 ) ->SetName( "vector" ); //std::cout << "array name = vectors now" << std::endl; } //std::cout << " projecting..."<< std::endl; // // constrain the vectors to lie on the plane, which means to remove the vector component, // which is orthogonal to the plane. // vtkIdType numPoints, pointId; numPoints = cuttedPlane->GetNumberOfPoints(); vtkDataArray* inVectors = cuttedPlane->GetPointData()->GetVectors( "vector" ); assert( inVectors != NULL ); vtkFloatArray* vectorMagnitudes = vtkFloatArray::New(); vectorMagnitudes->SetName("vectorMagnitudes"); vectorMagnitudes->SetNumberOfComponents(1); vectorMagnitudes->SetNumberOfValues(numPoints); vectorMagnitudes->SetNumberOfTuples(numPoints); vtkFloatingPointType inVector[ 3 ], outVector[3], wnormal[3]; //, tmpVector[ 3 ], outVector[ 3 ]; vtkFloatingPointType k = 0.0; vnl2vtk( normal.Get_vnl_vector(), wnormal ); vtkMath::Normalize( wnormal ); bool normalizeVecs; m_DataNode->GetBoolProperty( "NormalizeVecs", normalizeVecs ); for ( pointId = 0; pointId < numPoints; ++pointId ) { inVectors->GetTuple( pointId, inVector ); if(normalizeVecs) { vnl_vector tmp(3); vtk2vnl(inVector, tmp); tmp.normalize(); vnl2vtk(tmp, inVector); } k = vtkMath::Dot( wnormal, inVector ); // Remove non orthogonal component. outVector[ 0 ] = inVector[ 0 ] - ( wnormal[ 0 ] * k ); outVector[ 1 ] = inVector[ 1 ] - ( wnormal[ 1 ] * k ); outVector[ 2 ] = inVector[ 2 ] - ( wnormal[ 2 ] * k ); inVectors->SetTuple( pointId, outVector ); // ?? this was set to norm(inVector) before, but outVector made more sense to me vectorMagnitudes->SetValue( pointId, vtkMath::Norm( outVector ) ); //std::cout << "method old: " << inVector[0] <<", " << inVector[1] << ", "<AddArray(vectorMagnitudes); pointData->CopyAllOn(); //pointData->PrintSelf(std::cout, vtkIndent(4)); //std::cout << " ...done!"<< std::endl; //std::cout << " glyphing..."<< std::endl; // call glyph2D to generate 2D glyphs for each of the // vectors vtkGlyphSource2D* glyphSource = vtkGlyphSource2D::New(); //glyphSource->SetGlyphTypeToDash(); glyphSource->DashOn(); //glyphSource->SetScale( 0.1 ); //glyphSource->SetScale2( .5 ); //glyphSource->SetCenter( 0.5, 0.5, 0.5 ); glyphSource->CrossOff(); //glyphSource->FilledOff(); //glyphSource->Update(); double spacing[3]; vtkImage->GetSpacing(spacing); double min = spacing[0]; min = min > spacing[1] ? spacing[1] : min; min = min > spacing[2] ? spacing[2] : min; float scale = 1; mitk::FloatProperty::Pointer mitkScaleProp = dynamic_cast(GetDataNode()->GetProperty("Scale")); if (mitkScaleProp.IsNotNull()) { scale = mitkScaleProp->GetValue(); } vtkMaskedGlyph3D* glyphGenerator = vtkMaskedGlyph3D::New(); glyphGenerator->SetSource( glyphSource->GetOutput() ); glyphGenerator->SetInputConnection(cuttedPlane->GetProducerPort()); glyphGenerator->SetInputArrayToProcess (1, 0,0, vtkDataObject::FIELD_ASSOCIATION_POINTS , "vector"); glyphGenerator->SetVectorModeToUseVector(); glyphGenerator->OrientOn(); glyphGenerator->SetScaleFactor( min*scale ); glyphGenerator->SetUseMaskPoints( true ); glyphGenerator->SetRandomMode( true ); glyphGenerator->SetMaximumNumberOfPoints( 128*128 ); glyphGenerator->Update(); vtkLookupTable* vtkLut = NULL; mitk::LookupTableProperty::Pointer mitkLutProp = dynamic_cast(GetDataNode()->GetProperty("LookupTable")); if (mitkLutProp.IsNotNull()) { vtkLut = mitkLutProp->GetLookupTable()->GetVtkLookupTable(); } mitk::Color color; mitk::ColorProperty::Pointer mitkColorProp = dynamic_cast(GetDataNode()->GetProperty("color")); if (mitkColorProp.IsNotNull()) { color = mitkColorProp->GetColor(); } else { color.SetRed(0); color.SetBlue(1); color.SetGreen(0); } float lwidth = 1; mitk::FloatProperty::Pointer mitkLWidthProp = dynamic_cast(GetDataNode()->GetProperty("LineWidth")); if (mitkLWidthProp.IsNotNull()) { lwidth = mitkLWidthProp->GetValue(); } vtkTransform* trafo = vtkTransform::New(); trafo->Identity(); trafo->Concatenate(vtktransform); trafo->PreMultiply(); double myscale[3]; trafo->GetScale(myscale); trafo->Scale(1/myscale[0],1/myscale[1],1/myscale[2]); this->PaintCells( glyphGenerator->GetOutput(), renderer->GetCurrentWorldGeometry2D(), renderer->GetDisplayGeometry(), trafo, renderer, NULL/*vtkLut*/, color, lwidth, spacing ); vectorMagnitudes->Delete(); glyphSource->Delete(); glyphGenerator->Delete(); trafo->Delete(); } else { std::cout << " no points cutted!"<< std::endl; } //std::cout << "...done!" << std::endl; } void mitk::VectorImageMapper2D::PaintCells( vtkPolyData* glyphs, const Geometry2D* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform* vtktransform, mitk::BaseRenderer* /*renderer*/, vtkScalarsToColors *lut, mitk::Color color, float lwidth, vtkFloatingPointType *spacing ) { vtkPoints * points = glyphs->GetPoints(); vtkPointData * vpointdata = glyphs->GetPointData(); vtkDataArray* vpointscalars = vpointdata->GetArray("vectorMagnitudes"); //vtkDataArray* vpointpositions = vpointdata->GetArray("pointPositions"); assert(vpointscalars != NULL); //std::cout << " Scalars range 2d:" << vpointscalars->GetRange()[0] << " " << vpointscalars->GetRange()[0] << std::endl; Point3D p; Point2D p2d; vtkIdList* idList; vtkCell* cell; vtkFloatingPointType offset[3]; for (unsigned int i = 0; i < 3; ++i) { offset[i] = 0; } vtkIdType numCells = glyphs->GetNumberOfCells(); for ( vtkIdType cellId = 0; cellId < numCells; ++cellId ) { vtkFloatingPointType vp[ 3 ]; cell = glyphs->GetCell( cellId ); idList = cell->GetPointIds(); int numPoints = idList->GetNumberOfIds(); if(numPoints == 1) { //take transformation via vtktransform into account vtkFloatingPointType pos[ 3 ],vp_raster[3]; points->GetPoint( idList->GetId( 0 ), vp ); vp_raster[0] = vtkMath::Round(vp[0]/spacing[0])*spacing[0]; vp_raster[1] = vtkMath::Round(vp[1]/spacing[1])*spacing[1]; vp_raster[2] = vtkMath::Round(vp[2]/spacing[2])*spacing[2]; vtktransform->TransformPoint( vp_raster, pos ); offset[0] = pos[0] - vp[0]; offset[1] = pos[1] - vp[1]; offset[2] = pos[2] - vp[2]; } else { glLineWidth(lwidth); glBegin ( GL_LINE_LOOP ); for ( int pointNr = 0; pointNr < numPoints ;++pointNr ) { points->GetPoint( idList->GetId( pointNr ), vp ); vp[0] = vp[0] + offset[0]; vp[1] = vp[1] + offset[1]; vp[2] = vp[2] + offset[2]; vtkFloatingPointType tmp[ 3 ]; vtktransform->TransformPoint( vp,tmp ); vtk2itk( vp, p ); //convert 3D point (in mm) to 2D point on slice (also in mm) worldGeometry->Map( p, p2d ); //convert point (until now mm and in worldcoordinates) to display coordinates (units ) displayGeometry->WorldToDisplay( p2d, p2d ); if ( lut != NULL ) { // color each point according to point data vtkFloatingPointType * color; if ( vpointscalars != NULL ) { vpointscalars->GetComponent( pointNr, 0 ); color = lut->GetColor( vpointscalars->GetComponent( idList->GetId( pointNr ), 0 ) ); glColor3f( color[ 0 ], color[ 1 ], color[ 2 ] ); } } else { glColor3f( color.GetRed(), color.GetGreen(), color.GetBlue() ); } //std::cout << idList->GetId( pointNr )<< ": " << p2d[0]<< " "<< p2d[1] << std::endl; //draw the line glVertex2f( p2d[ 0 ], p2d[ 1 ] ); } glEnd (); } } } mitk::VectorImageMapper2D::VectorImageMapper2D() { m_LUT = NULL; m_Plane = vtkPlane::New(); m_Cutter = vtkCutter::New(); m_Cutter->SetCutFunction( m_Plane ); m_Cutter->GenerateValues( 1, 0, 1 ); } mitk::VectorImageMapper2D::~VectorImageMapper2D() { if ( m_LUT != NULL ) m_LUT->Delete(); if ( m_Plane != NULL ) m_Plane->Delete(); if ( m_Cutter != NULL ) m_Cutter->Delete(); } int mitk::VectorImageMapper2D::GetCurrentTimeStep( mitk::BaseData* data, mitk::BaseRenderer* renderer ) { // // get the TimeSlicedGeometry of the input object // const TimeSlicedGeometry * dataTimeGeometry = data->GetUpdatedTimeSlicedGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->GetTimeSteps() == 0 ) ) { itkWarningMacro( << "geometry of the given data object isn't a mitk::TimeSlicedGeometry, or the number of time steps is 0!" ); return 0; } // // get the world time // Geometry2D::ConstPointer worldGeometry = renderer->GetCurrentWorldGeometry2D(); assert( worldGeometry.IsNotNull() ); ScalarType time = worldGeometry->GetTimeBounds() [ 0 ]; // // convert the world time to time steps of the input object // int timestep = 0; if ( time > ScalarTypeNumericTraits::NonpositiveMin() ) timestep = dataTimeGeometry->MSToTimeStep( time ); if ( dataTimeGeometry->IsValidTime( timestep ) == false ) { itkWarningMacro( << timestep << " is not a valid time of the given data object!" ); return 0; } return timestep; } diff --git a/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.h b/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.h index 5f41732e67..28013b1380 100644 --- a/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.h +++ b/Modules/MitkExt/Rendering/mitkVectorImageMapper2D.h @@ -1,93 +1,93 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_VECTOR_IMAGE_MAPPER_2D__H_ #define _MITK_VECTOR_IMAGE_MAPPER_2D__H_ #include "MitkExtExports.h" #include "mitkCommon.h" -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" #include "mitkImage.h" class vtkLookupTable; class vtkScalarsToColors; class vtkImageReslice; class vtkPolyData; class vtkGlyph2D; class vtkPlane; class vtkCutter; namespace mitk { class BaseRenderer; class Geometry2D; class DisplayGeometry; -class MitkExt_EXPORT VectorImageMapper2D : public GLMapper2D +class MitkExt_EXPORT VectorImageMapper2D : public GLMapper { public: - mitkClassMacro( VectorImageMapper2D, GLMapper2D ); + mitkClassMacro( VectorImageMapper2D, GLMapper ); itkNewMacro( Self ); typedef vtkFloatingPointType vtkScalarType; /** * @returns the image held by the associated with the mapper or the image * which has been explicitly set by SetImage(...) */ const mitk::Image * GetInput( void ); virtual void Paint( mitk::BaseRenderer * renderer ); /** * Explicitly set an vector image. This image will be used for * rendering instead of the image returned by GetData() */ itkSetConstObjectMacro( Image, mitk::Image ); /** * Get the explicitly set image * @returns NULL if no Image has been set instead of GetData(); */ itkGetConstObjectMacro( Image, mitk::Image ); virtual void PaintCells( vtkPolyData* contour, const Geometry2D* worldGeometry, const DisplayGeometry* displayGeometry, vtkLinearTransform* vtktransform, BaseRenderer* renderer, vtkScalarsToColors *lut, mitk::Color color, float lwidth, vtkFloatingPointType *spacing ); protected: int GetCurrentTimeStep( mitk::BaseData* data, mitk::BaseRenderer* renderer ); VectorImageMapper2D(); virtual ~VectorImageMapper2D(); mitk::Image::ConstPointer m_Image; vtkLookupTable *m_LUT; vtkPlane* m_Plane; vtkCutter* m_Cutter; }; } // namespace mitk #endif diff --git a/Modules/MitkExt/Testing/mitkDataNodeExtTest.cpp b/Modules/MitkExt/Testing/mitkDataNodeExtTest.cpp index 7cd3a45f9c..5b9dfd95b8 100644 --- a/Modules/MitkExt/Testing/mitkDataNodeExtTest.cpp +++ b/Modules/MitkExt/Testing/mitkDataNodeExtTest.cpp @@ -1,213 +1,213 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDataNode.h" #include #include "mitkVtkPropRenderer.h" #include "mitkTestingMacros.h" #include "mitkGlobalInteraction.h" #include //Basedata Test #include #include #include #include #include //Mapper Test #include -#include -#include +#include +#include #include #include #include #include #include #include #include #include //Interactors #include #include #include #include #include //Propertylist Test #include #include #include #include #include #include #include #include #include #include #include /** * Extended test for mitk::DataNode. A number of tests from the core test * mitkDataNodeTest are assumed to pass! */ class mitkDataNodeExtTestClass { public: static void TestDataSetting(mitk::DataNode::Pointer dataNode) { mitk::BaseData::Pointer baseData; //NULL pointer Test dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a NULL pointer was set correctly" ) baseData = mitk::ItkBaseDataAdapter::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a ItkBaseDataAdapter object was set correctly" ) baseData = mitk::Mesh::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a Mesh object was set correctly" ) baseData = mitk::SeedsImage::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a SeedsImage object was set correctly" ) baseData = mitk::BoundingObject::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a BoundingObject object was set correctly" ) baseData = mitk::UnstructuredGrid::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a UnstructuredGrid object was set correctly" ) } static void TestMapperSetting(mitk::DataNode::Pointer dataNode) { //tests the SetMapper() method //in dataNode is a mapper vector which can be accessed by index //in this test method we use only slot 0 (filled with null) and slot 1 //so we also test the destructor of the mapper classes mitk::Mapper::Pointer mapper; dataNode->SetMapper(0,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(0), "Testing if a NULL pointer was set correctly" ) mapper = mitk::MeshMapper2D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a MeshMapper2D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::UnstructuredGridMapper2D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a UnstructuredGridMapper2D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::LineMapper2D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a LineMapper2D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::SplineMapper2D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a SplineMapper2D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::MeshVtkMapper3D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a MeshVtkMapper3D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::UnstructuredGridVtkMapper3D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a UnstructuredGridVtkMapper3D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) //linker error //mapper = mitk::LineVtkMapper3D::New(); //dataNode->SetMapper(1,mapper); //MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a LineVtkMapper3D was set correctly" ) //MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::SplineVtkMapper3D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a SplineVtkMapper3D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) } static void TestInteractorSetting(mitk::DataNode::Pointer dataNode) { //this method tests the SetInteractor() and GetInteractor methods //the Interactor base class calls the DataNode->SetInteractor method mitk::Interactor::Pointer interactor; MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a NULL pointer was set correctly (Interactor)" ) interactor = mitk::ConnectPointsInteractor::New("AffineInteractions click to select", dataNode); MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a ConnectPointsInteractor was set correctly" ) interactor = mitk::PointInteractor::New("AffineInteractions click to select", dataNode); MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a PointInteractor was set correctly" ) interactor = mitk::PointSelectorInteractor::New("AffineInteractions click to select", dataNode); MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a PointSelectorInteractor was set correctly" ) interactor = mitk::SeedsInteractor::New("AffineInteractions click to select", dataNode); MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a SeedsInteractor was set correctly" ) interactor = mitk::DisplayPointSetInteractor::New("AffineInteractions click to select", dataNode); MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a DisplayPointSetInteractor was set correctly" ) } }; int mitkDataNodeExtTest(int /* argc */, char* /*argv*/[]) { // always start with this! MITK_TEST_BEGIN("DataNode") // Global interaction must(!) be initialized mitk::GlobalInteraction::GetInstance()->Initialize("global"); // let's create an object of our class mitk::DataNode::Pointer myDataNode = mitk::DataNode::New(); // first test: did this work? // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since // it makes no sense to continue without an object. MITK_TEST_CONDITION_REQUIRED(myDataNode.IsNotNull(),"Testing instantiation") //test setData() Method mitkDataNodeExtTestClass::TestDataSetting(myDataNode); mitkDataNodeExtTestClass::TestMapperSetting(myDataNode); //note, that no data is set to the dataNode mitkDataNodeExtTestClass::TestInteractorSetting(myDataNode); // write your own tests here and use the macros from mitkTestingMacros.h !!! // do not write to std::cout and do not return from this function yourself! // always end with this! MITK_TEST_END() } diff --git a/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp b/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp index 6f225b3812..9f77172bcf 100644 --- a/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp +++ b/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.cpp @@ -1,753 +1,754 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPlanarFigureMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkGL.h" #include "mitkVtkPropRenderer.h" #define _USE_MATH_DEFINES #include // offset which moves the planarfigures on top of the other content // the crosshair is rendered into the z = 1 layer. static const float PLANAR_OFFSET = 0.5f; mitk::PlanarFigureMapper2D::PlanarFigureMapper2D() { this->InitializeDefaultPlanarFigureProperties(); } mitk::PlanarFigureMapper2D::~PlanarFigureMapper2D() { } void mitk::PlanarFigureMapper2D::Paint( mitk::BaseRenderer *renderer ) { - if ( !this->IsVisible( renderer ) ) - { - return; - } + + bool visible = true; + + GetDataNode()->GetVisibility(visible, renderer, "visible"); + if ( !visible ) return; // Get PlanarFigure from input mitk::PlanarFigure *planarFigure = const_cast< mitk::PlanarFigure * >( - static_cast< const mitk::PlanarFigure * >( this->GetData() ) ); + static_cast< const mitk::PlanarFigure * >( GetDataNode()->GetData() ) ); // Check if PlanarFigure has already been placed; otherwise, do nothing if ( !planarFigure->IsPlaced() ) { return; } // Get 2D geometry frame of PlanarFigure mitk::Geometry2D *planarFigureGeometry2D = dynamic_cast< Geometry2D * >( planarFigure->GetGeometry( 0 ) ); if ( planarFigureGeometry2D == NULL ) { MITK_ERROR << "PlanarFigure does not have valid Geometry2D!"; return; } // Get current world 2D geometry from renderer const mitk::Geometry2D *rendererGeometry2D = renderer->GetCurrentWorldGeometry2D(); // If the PlanarFigure geometry is a plane geometry, check if current // world plane is parallel to and within the planar figure geometry bounds // (otherwise, display nothing) mitk::PlaneGeometry *planarFigurePlaneGeometry = dynamic_cast< PlaneGeometry * >( planarFigureGeometry2D ); const mitk::PlaneGeometry *rendererPlaneGeometry = dynamic_cast< const PlaneGeometry * >( rendererGeometry2D ); if ( (planarFigurePlaneGeometry != NULL) && (rendererPlaneGeometry != NULL) ) { double planeThickness = planarFigurePlaneGeometry->GetExtentInMM( 2 ); if ( !planarFigurePlaneGeometry->IsParallel( rendererPlaneGeometry ) || !(planarFigurePlaneGeometry->DistanceFromPlane( rendererPlaneGeometry ) < planeThickness / 3.0) ) { // Planes are not parallel or renderer plane is not within PlanarFigure // geometry bounds --> exit return; } } else { // Plane is not valid (curved reformations are not possible yet) return; } // Get display geometry mitk::DisplayGeometry *displayGeometry = renderer->GetDisplayGeometry(); assert( displayGeometry != NULL ); // Apply visual appearance properties from the PropertyList - this->ApplyProperties( renderer ); + ApplyColorAndOpacityProperties( renderer ); // Enable line antialiasing glEnable( GL_LINE_SMOOTH ); glHint( GL_LINE_SMOOTH_HINT, GL_NICEST ); glEnable(GL_DEPTH_TEST); // Get properties from node (if present) const mitk::DataNode* node=this->GetDataNode(); this->InitializePlanarFigurePropertiesFromDataNode( node ); PlanarFigureDisplayMode lineDisplayMode = PF_DEFAULT; if ( m_IsSelected ) { lineDisplayMode = PF_SELECTED; } else if ( m_IsHovering ) { lineDisplayMode = PF_HOVER; } mitk::Point2D firstPoint; firstPoint[0] = 0; firstPoint[1] = 1; if ( m_DrawOutline ) { // Draw the outline for all polylines if requested this->DrawMainLines( planarFigure, m_OutlineColor[lineDisplayMode], m_OutlineOpacity[lineDisplayMode], m_DrawShadow, m_OutlineWidth, m_ShadowWidthFactor, firstPoint, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); // Draw the outline for all helper objects if requested this->DrawHelperLines( planarFigure, m_OutlineColor[lineDisplayMode], m_OutlineOpacity[lineDisplayMode], m_DrawShadow, m_OutlineWidth, m_ShadowWidthFactor, firstPoint, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); } // Draw the main line for all polylines this->DrawMainLines( planarFigure, m_LineColor[lineDisplayMode], m_LineOpacity[lineDisplayMode], m_DrawShadow, m_LineWidth, m_ShadowWidthFactor, firstPoint, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); double annotationOffset = 0.0; //Get Global Opacity float globalOpacity = 1.0; node->GetFloatProperty("opacity", globalOpacity); // draw name near the first point (if present) std::string name = node->GetName(); if ( m_DrawName && !name.empty() ) { mitk::VtkPropRenderer* openGLrenderer = dynamic_cast( renderer ); if ( openGLrenderer ) { openGLrenderer->WriteSimpleText( name, firstPoint[0] + 6.0, firstPoint[1] + 4.0, 0, 0, 0, globalOpacity ); //this is a shadow openGLrenderer->WriteSimpleText( name, firstPoint[0] + 5.0, firstPoint[1] + 5.0, m_LineColor[lineDisplayMode][0], m_LineColor[lineDisplayMode][1], m_LineColor[lineDisplayMode][2], globalOpacity ); // If drawing is successful, add approximate height to annotation offset annotationOffset -= 15.0; } } // draw feature quantities (if requested) new the first point if ( m_DrawQuantities ) { std::stringstream quantityString; quantityString.setf( ios::fixed, ios::floatfield ); quantityString.precision( 1 ); bool firstActiveFeature = true; for ( unsigned int i = 0; i < planarFigure->GetNumberOfFeatures(); ++i ) { if( planarFigure->IsFeatureActive(i) && planarFigure->IsFeatureVisible( i ) ) { if ( ! firstActiveFeature ) { quantityString << " x "; } quantityString << planarFigure->GetQuantity( i ) << " "; quantityString << planarFigure->GetFeatureUnit( i ); firstActiveFeature = false; } } mitk::VtkPropRenderer* openGLrenderer = dynamic_cast( renderer ); if ( openGLrenderer ) { openGLrenderer->WriteSimpleText( quantityString.str().c_str(), firstPoint[0] + 6.0, firstPoint[1] + 4.0 + annotationOffset, 0, 0, 0, globalOpacity ); //this is a shadow openGLrenderer->WriteSimpleText( quantityString.str().c_str(), firstPoint[0] + 5.0, firstPoint[1] + 5.0 + annotationOffset, m_LineColor[lineDisplayMode][0], m_LineColor[lineDisplayMode][1], m_LineColor[lineDisplayMode][2], globalOpacity ); // If drawing is successful, add approximate height to annotation offset annotationOffset -= 15.0; } } // Draw helper objects this->DrawHelperLines( planarFigure, m_HelperlineColor[lineDisplayMode], m_HelperlineOpacity[lineDisplayMode], m_DrawShadow, m_LineWidth, m_ShadowWidthFactor, firstPoint, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); if ( m_DrawControlPoints ) { // Draw markers at control points (selected control point will be colored) for ( unsigned int i = 0; i < planarFigure->GetNumberOfControlPoints(); ++i ) { bool isEditable = true; m_DataNode->GetBoolProperty( "planarfigure.iseditable", isEditable ); PlanarFigureDisplayMode pointDisplayMode = PF_DEFAULT; // Only if planar figure is marked as editable: display markers (control points) in a // different style if mouse is over them or they are selected if ( isEditable ) { if ( i == (unsigned int) planarFigure->GetSelectedControlPoint() ) { pointDisplayMode = PF_SELECTED; } else if ( m_IsHovering ) { pointDisplayMode = PF_HOVER; } } if ( m_DrawOutline ) { // draw outlines for markers as well // linewidth for the contour is only half, as full width looks // much too thick! this->DrawMarker( planarFigure->GetControlPoint( i ), m_OutlineColor[lineDisplayMode], m_MarkerlineOpacity[pointDisplayMode], m_OutlineColor[lineDisplayMode], m_MarkerOpacity[pointDisplayMode], m_OutlineWidth/2, m_ControlPointShape, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); } this->DrawMarker( planarFigure->GetControlPoint( i ), m_MarkerlineColor[pointDisplayMode], m_MarkerlineOpacity[pointDisplayMode], m_MarkerColor[pointDisplayMode], m_MarkerOpacity[pointDisplayMode], m_LineWidth, m_ControlPointShape, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); } if ( planarFigure->IsPreviewControlPointVisible() ) { this->DrawMarker( planarFigure->GetPreviewControlPoint(), m_MarkerlineColor[PF_HOVER], m_MarkerlineOpacity[PF_HOVER], m_MarkerColor[PF_HOVER], m_MarkerOpacity[PF_HOVER], m_LineWidth, m_ControlPointShape, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); } } glLineWidth( 1.0f ); } void mitk::PlanarFigureMapper2D::PaintPolyLine( mitk::PlanarFigure::PolyLineType vertices, bool closed, float* color, float opacity, float lineWidth, Point2D& firstPoint, const Geometry2D* planarFigureGeometry2D, const Geometry2D* rendererGeometry2D, const DisplayGeometry* displayGeometry) { glColor4f( color[0], color[1], color[2], opacity ); glLineWidth(lineWidth); glBegin( GL_LINE_STRIP ); for ( PlanarFigure::PolyLineType::iterator iter = vertices.begin(); iter!=vertices.end(); iter++ ) { // Draw this 2D point as OpenGL vertex mitk::Point2D displayPoint; this->TransformObjectToDisplay( iter->Point, displayPoint, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); if(iter == vertices.begin()) firstPoint = displayPoint; glVertex3f( displayPoint[0], displayPoint[1], PLANAR_OFFSET ); } if(closed) { // complete line loop to the first point again mitk::Point2D displayPoint; this->TransformObjectToDisplay( vertices.begin()->Point, displayPoint, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); glVertex3f( displayPoint[0], displayPoint[1], PLANAR_OFFSET ); } glEnd(); } void mitk::PlanarFigureMapper2D::DrawMainLines( mitk::PlanarFigure* figure, float* color, float opacity, bool drawShadow, float lineWidth, float shadowWidthFactor, Point2D& firstPoint, const Geometry2D* planarFigureGeometry2D, const Geometry2D* rendererGeometry2D, const DisplayGeometry* displayGeometry) { for ( unsigned short loop = 0; loop < figure->GetPolyLinesSize(); ++loop ) { PlanarFigure::PolyLineType polyline = figure->GetPolyLine(loop); if ( drawShadow ) { float* shadow = new float[3]; shadow[0] = 0; shadow[1] = 0; shadow[2] = 0; //set shadow opacity float shadowOpacity = 0.0f; if( opacity > 0.2f ) shadowOpacity = opacity - 0.2f; this->PaintPolyLine( polyline, figure->IsClosed(), shadow, shadowOpacity, lineWidth*shadowWidthFactor, firstPoint, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); delete shadow; } this->PaintPolyLine( polyline, figure->IsClosed(), color, opacity, lineWidth, firstPoint, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); } } void mitk::PlanarFigureMapper2D::DrawHelperLines( mitk::PlanarFigure* figure, float* color, float opacity, bool drawShadow, float lineWidth, float shadowWidthFactor, Point2D& firstPoint, const Geometry2D* planarFigureGeometry2D, const Geometry2D* rendererGeometry2D, const DisplayGeometry* displayGeometry) { // Draw helper objects for ( unsigned int loop = 0; loop < figure->GetHelperPolyLinesSize(); ++loop ) { const mitk::PlanarFigure::PolyLineType helperPolyLine = figure->GetHelperPolyLine(loop, displayGeometry->GetScaleFactorMMPerDisplayUnit(), displayGeometry->GetDisplayHeight() ); // Check if the current helper objects is to be painted if ( !figure->IsHelperToBePainted( loop ) ) { continue; } // check if shadow shall be painted around the figure if ( drawShadow ) { float* shadow = new float[3]; shadow[0] = 0; shadow[1] = 0; shadow[2] = 0; //set shadow opacity float shadowOpacity = 0.0f; if( opacity > 0.2f ) shadowOpacity = opacity - 0.2f; // paint shadow by painting the figure twice // one in black with a slightly broader line-width ... this->PaintPolyLine( helperPolyLine, false, shadow, shadowOpacity, lineWidth*shadowWidthFactor, firstPoint, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); delete shadow; } // ... and once normally above the shadow. this->PaintPolyLine( helperPolyLine, false, color, opacity, lineWidth, firstPoint, planarFigureGeometry2D, rendererGeometry2D, displayGeometry ); } } void mitk::PlanarFigureMapper2D::TransformObjectToDisplay( const mitk::Point2D &point2D, mitk::Point2D &displayPoint, const mitk::Geometry2D *objectGeometry, const mitk::Geometry2D *rendererGeometry, const mitk::DisplayGeometry *displayGeometry ) { mitk::Point3D point3D; // Map circle point from local 2D geometry into 3D world space objectGeometry->Map( point2D, point3D ); // Project 3D world point onto display geometry rendererGeometry->Map( point3D, displayPoint ); displayGeometry->WorldToDisplay( displayPoint, displayPoint ); } void mitk::PlanarFigureMapper2D::DrawMarker( const mitk::Point2D &point, float* lineColor, float lineOpacity, float* markerColor, float markerOpacity, float lineWidth, PlanarFigureControlPointStyleProperty::Shape shape, const mitk::Geometry2D *objectGeometry, const mitk::Geometry2D *rendererGeometry, const mitk::DisplayGeometry *displayGeometry ) { mitk::Point2D displayPoint; if ( markerOpacity == 0 && lineOpacity == 0 ) return; this->TransformObjectToDisplay( point, displayPoint, objectGeometry, rendererGeometry, displayGeometry ); glColor4f( markerColor[0], markerColor[1], markerColor[2], markerOpacity ); glLineWidth( lineWidth ); switch ( shape ) { case PlanarFigureControlPointStyleProperty::Square: default: // Paint filled square // Disable line antialiasing (does not look nice for squares) glDisable( GL_LINE_SMOOTH ); glRectf( displayPoint[0] - 4, displayPoint[1] - 4, displayPoint[0] + 4, displayPoint[1] + 4 ); // Paint outline glColor4f( lineColor[0], lineColor[1], lineColor[2], lineOpacity ); glBegin( GL_LINE_LOOP ); glVertex3f( displayPoint[0] - 4, displayPoint[1] - 4, PLANAR_OFFSET ); glVertex3f( displayPoint[0] - 4, displayPoint[1] + 4, PLANAR_OFFSET ); glVertex3f( displayPoint[0] + 4, displayPoint[1] + 4, PLANAR_OFFSET ); glVertex3f( displayPoint[0] + 4, displayPoint[1] - 4, PLANAR_OFFSET ); glEnd(); break; case PlanarFigureControlPointStyleProperty::Circle: // Paint filled circle glBegin( GL_POLYGON ); float radius = 4.0; for ( int angle = 0; angle < 8; ++angle ) { float angleRad = angle * (float) 3.14159 / 4.0; float x = displayPoint[0] + radius * (float)cos( angleRad ); float y = displayPoint[1] + radius * (float)sin( angleRad ); glVertex3f(x, y, PLANAR_OFFSET); } glEnd(); // Paint outline glColor4f( lineColor[0], lineColor[1], lineColor[2], lineOpacity ); glBegin( GL_LINE_LOOP ); for ( int angle = 0; angle < 8; ++angle ) { float angleRad = angle * (float) 3.14159 / 4.0; float x = displayPoint[0] + radius * (float)cos( angleRad ); float y = displayPoint[1] + radius * (float)sin( angleRad ); glVertex3f(x, y, PLANAR_OFFSET); } glEnd(); break; } // end switch } void mitk::PlanarFigureMapper2D::InitializeDefaultPlanarFigureProperties() { m_IsSelected = false; m_IsHovering = false; m_DrawOutline = false; m_DrawQuantities = false; m_DrawShadow = false; m_DrawControlPoints = false; m_DrawName = true; m_ShadowWidthFactor = 1.2; m_LineWidth = 1.0; m_OutlineWidth = 4.0; m_HelperlineWidth = 2.0; m_ControlPointShape = PlanarFigureControlPointStyleProperty::Square; this->SetColorProperty( m_LineColor, PF_DEFAULT, 1.0, 1.0, 1.0 ); this->SetFloatProperty( m_LineOpacity, PF_DEFAULT, 1.0 ); this->SetColorProperty( m_OutlineColor, PF_DEFAULT, 0.0, 0.0, 1.0 ); this->SetFloatProperty( m_OutlineOpacity, PF_DEFAULT, 1.0 ); this->SetColorProperty( m_HelperlineColor, PF_DEFAULT, 0.4, 0.8, 0.2 ); this->SetFloatProperty( m_HelperlineOpacity, PF_DEFAULT, 0.4 ); this->SetColorProperty( m_MarkerlineColor, PF_DEFAULT, 1.0, 1.0, 1.0 ); this->SetFloatProperty( m_MarkerlineOpacity, PF_DEFAULT, 1.0 ); this->SetColorProperty( m_MarkerColor, PF_DEFAULT, 1.0, 1.0, 1.0 ); this->SetFloatProperty( m_MarkerOpacity, PF_DEFAULT, 0.0 ); this->SetColorProperty( m_LineColor, PF_HOVER, 1.0, 0.7, 0.0 ); this->SetFloatProperty( m_LineOpacity, PF_HOVER, 1.0 ); this->SetColorProperty( m_OutlineColor, PF_HOVER, 0.0, 0.0, 1.0 ); this->SetFloatProperty( m_OutlineOpacity, PF_HOVER, 1.0 ); this->SetColorProperty( m_HelperlineColor, PF_HOVER, 0.4, 0.8, 0.2 ); this->SetFloatProperty( m_HelperlineOpacity, PF_HOVER, 0.4 ); this->SetColorProperty( m_MarkerlineColor, PF_HOVER, 1.0, 1.0, 1.0 ); this->SetFloatProperty( m_MarkerlineOpacity, PF_HOVER, 1.0 ); this->SetColorProperty( m_MarkerColor, PF_HOVER, 1.0, 0.6, 0.0 ); this->SetFloatProperty( m_MarkerOpacity, PF_HOVER, 0.2 ); this->SetColorProperty( m_LineColor, PF_SELECTED, 1.0, 0.0, 0.0 ); this->SetFloatProperty( m_LineOpacity, PF_SELECTED, 1.0 ); this->SetColorProperty( m_OutlineColor, PF_SELECTED, 0.0, 0.0, 1.0 ); this->SetFloatProperty( m_OutlineOpacity, PF_SELECTED, 1.0 ); this->SetColorProperty( m_HelperlineColor, PF_SELECTED, 0.4, 0.8, 0.2 ); this->SetFloatProperty( m_HelperlineOpacity, PF_SELECTED, 0.4 ); this->SetColorProperty( m_MarkerlineColor, PF_SELECTED, 1.0, 1.0, 1.0 ); this->SetFloatProperty( m_MarkerlineOpacity, PF_SELECTED, 1.0 ); this->SetColorProperty( m_MarkerColor, PF_SELECTED, 1.0, 0.6, 0.0 ); this->SetFloatProperty( m_MarkerOpacity, PF_SELECTED, 1.0 ); } void mitk::PlanarFigureMapper2D::InitializePlanarFigurePropertiesFromDataNode( const mitk::DataNode* node ) { if ( node == NULL ) { return; } //Get Global Opacity float globalOpacity = 1.0; node->GetFloatProperty("opacity", globalOpacity); node->GetBoolProperty( "selected", m_IsSelected ); node->GetBoolProperty( "planarfigure.ishovering", m_IsHovering ); node->GetBoolProperty( "planarfigure.drawoutline", m_DrawOutline ); node->GetBoolProperty( "planarfigure.drawshadow", m_DrawShadow ); node->GetBoolProperty( "planarfigure.drawquantities", m_DrawQuantities ); node->GetBoolProperty( "planarfigure.drawcontrolpoints", m_DrawControlPoints ); node->GetBoolProperty( "planarfigure.drawname", m_DrawName ); node->GetFloatProperty( "planarfigure.line.width", m_LineWidth ); node->GetFloatProperty( "planarfigure.shadow.widthmodifier", m_ShadowWidthFactor ); node->GetFloatProperty( "planarfigure.outline.width", m_OutlineWidth ); node->GetFloatProperty( "planarfigure.helperline.width", m_HelperlineWidth ); PlanarFigureControlPointStyleProperty::Pointer styleProperty = dynamic_cast< PlanarFigureControlPointStyleProperty* >( node->GetProperty( "planarfigure.controlpointshape" ) ); if ( styleProperty.IsNotNull() ) { m_ControlPointShape = styleProperty->GetShape(); } //Set default color and opacity //If property "planarfigure.default.*.color" exists, then use that color. Otherwise global "color" property is used. if( !node->GetColor( m_LineColor[PF_DEFAULT], NULL, "planarfigure.default.line.color")) { node->GetColor( m_LineColor[PF_DEFAULT], NULL, "color" ); } node->GetFloatProperty( "planarfigure.default.line.opacity", m_LineOpacity[PF_DEFAULT] ); if( !node->GetColor( m_OutlineColor[PF_DEFAULT], NULL, "planarfigure.default.outline.color")) { node->GetColor( m_OutlineColor[PF_DEFAULT], NULL, "color" ); } node->GetFloatProperty( "planarfigure.default.outline.opacity", m_OutlineOpacity[PF_DEFAULT] ); if( !node->GetColor( m_HelperlineColor[PF_DEFAULT], NULL, "planarfigure.default.helperline.color")) { node->GetColor( m_HelperlineColor[PF_DEFAULT], NULL, "color" ); } node->GetFloatProperty( "planarfigure.default.helperline.opacity", m_HelperlineOpacity[PF_DEFAULT] ); node->GetColor( m_MarkerlineColor[PF_DEFAULT], NULL, "planarfigure.default.markerline.color" ); node->GetFloatProperty( "planarfigure.default.markerline.opacity", m_MarkerlineOpacity[PF_DEFAULT] ); node->GetColor( m_MarkerColor[PF_DEFAULT], NULL, "planarfigure.default.marker.color" ); node->GetFloatProperty( "planarfigure.default.marker.opacity", m_MarkerOpacity[PF_DEFAULT] ); //Set hover color and opacity node->GetColor( m_LineColor[PF_HOVER], NULL, "planarfigure.hover.line.color" ); node->GetFloatProperty( "planarfigure.hover.line.opacity", m_LineOpacity[PF_HOVER] ); node->GetColor( m_OutlineColor[PF_HOVER], NULL, "planarfigure.hover.outline.color" ); node->GetFloatProperty( "planarfigure.hover.outline.opacity", m_OutlineOpacity[PF_HOVER] ); node->GetColor( m_HelperlineColor[PF_HOVER], NULL, "planarfigure.hover.helperline.color" ); node->GetFloatProperty( "planarfigure.hover.helperline.opacity", m_HelperlineOpacity[PF_HOVER] ); node->GetColor( m_MarkerlineColor[PF_HOVER], NULL, "planarfigure.hover.markerline.color" ); node->GetFloatProperty( "planarfigure.hover.markerline.opacity", m_MarkerlineOpacity[PF_HOVER] ); node->GetColor( m_MarkerColor[PF_HOVER], NULL, "planarfigure.hover.marker.color" ); node->GetFloatProperty( "planarfigure.hover.marker.opacity", m_MarkerOpacity[PF_HOVER] ); //Set selected color and opacity node->GetColor( m_LineColor[PF_SELECTED], NULL, "planarfigure.selected.line.color" ); node->GetFloatProperty( "planarfigure.selected.line.opacity", m_LineOpacity[PF_SELECTED] ); node->GetColor( m_OutlineColor[PF_SELECTED], NULL, "planarfigure.selected.outline.color" ); node->GetFloatProperty( "planarfigure.selected.outline.opacity", m_OutlineOpacity[PF_SELECTED] ); node->GetColor( m_HelperlineColor[PF_SELECTED], NULL, "planarfigure.selected.helperline.color" ); node->GetFloatProperty( "planarfigure.selected.helperline.opacity", m_HelperlineOpacity[PF_SELECTED] ); node->GetColor( m_MarkerlineColor[PF_SELECTED], NULL, "planarfigure.selected.markerline.color" ); node->GetFloatProperty( "planarfigure.selected.markerline.opacity", m_MarkerlineOpacity[PF_SELECTED] ); node->GetColor( m_MarkerColor[PF_SELECTED], NULL, "planarfigure.selected.marker.color" ); node->GetFloatProperty( "planarfigure.selected.marker.opacity", m_MarkerOpacity[PF_SELECTED] ); //adapt opacity values to global "opacity" property for( unsigned int i = 0; i < PF_COUNT; ++i ) { m_LineOpacity[i] *= globalOpacity; m_OutlineOpacity[i] *= globalOpacity; m_HelperlineOpacity[i] *= globalOpacity; m_MarkerlineOpacity[i] *= globalOpacity; m_MarkerOpacity[i] *= globalOpacity; } } void mitk::PlanarFigureMapper2D::SetDefaultProperties( mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite ) { node->AddProperty( "visible", mitk::BoolProperty::New(true), renderer, overwrite ); //node->SetProperty("planarfigure.iseditable",mitk::BoolProperty::New(true)); //node->SetProperty("planarfigure.isextendable",mitk::BoolProperty::New(true)); //node->AddProperty( "planarfigure.ishovering", mitk::BoolProperty::New(true) ); node->AddProperty( "planarfigure.drawoutline", mitk::BoolProperty::New(true) ); //node->AddProperty( "planarfigure.drawquantities", mitk::BoolProperty::New(true) ); node->AddProperty( "planarfigure.drawshadow", mitk::BoolProperty::New(true) ); node->AddProperty( "planarfigure.drawcontrolpoints", mitk::BoolProperty::New(true) ); node->AddProperty( "planarfigure.drawname", mitk::BoolProperty::New(true) ); node->AddProperty("planarfigure.line.width", mitk::FloatProperty::New(2.0) ); node->AddProperty("planarfigure.shadow.widthmodifier", mitk::FloatProperty::New(2.0) ); node->AddProperty("planarfigure.outline.width", mitk::FloatProperty::New(2.0) ); node->AddProperty("planarfigure.helperline.width", mitk::FloatProperty::New(2.0) ); node->AddProperty( "planarfigure.default.line.opacity", mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.default.outline.opacity", mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.default.helperline.opacity", mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.default.markerline.color", mitk::ColorProperty::New(1.0,1.0,1.0) ); node->AddProperty( "planarfigure.default.markerline.opacity", mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.default.marker.color", mitk::ColorProperty::New(1.0,1.0,1.0) ); node->AddProperty( "planarfigure.default.marker.opacity",mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.hover.line.color", mitk::ColorProperty::New(0.0,1.0,0.0) ); node->AddProperty( "planarfigure.hover.line.opacity", mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.hover.outline.color", mitk::ColorProperty::New(0.0,1.0,0.0) ); node->AddProperty( "planarfigure.hover.outline.opacity", mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.hover.helperline.color", mitk::ColorProperty::New(0.0,1.0,0.0) ); node->AddProperty( "planarfigure.hover.helperline.opacity", mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.hover.markerline.color", mitk::ColorProperty::New(0.0,1.0,0.0) ); node->AddProperty( "planarfigure.hover.markerline.opacity", mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.hover.marker.color", mitk::ColorProperty::New(0.0,1.0,0.0) ); node->AddProperty( "planarfigure.hover.marker.opacity", mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.selected.line.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); node->AddProperty( "planarfigure.selected.line.opacity",mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.selected.outline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); node->AddProperty( "planarfigure.selected.outline.opacity", mitk::FloatProperty::New(1.0)); node->AddProperty( "planarfigure.selected.helperline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); node->AddProperty( "planarfigure.selected.helperline.opacity",mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.selected.markerline.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); node->AddProperty( "planarfigure.selected.markerline.opacity", mitk::FloatProperty::New(1.0) ); node->AddProperty( "planarfigure.selected.marker.color", mitk::ColorProperty::New(1.0,0.0,0.0) ); node->AddProperty( "planarfigure.selected.marker.opacity",mitk::FloatProperty::New(1.0)); } diff --git a/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.h b/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.h index e7fbe6f388..cac9489522 100644 --- a/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.h +++ b/Modules/PlanarFigure/Rendering/mitkPlanarFigureMapper2D.h @@ -1,244 +1,244 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITK_PLANAR_FIGURE_MAPPER_2D_H_ #define MITK_PLANAR_FIGURE_MAPPER_2D_H_ #include "mitkCommon.h" #include "PlanarFigureExports.h" -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" #include "mitkPlanarFigure.h" #include "mitkPlanarFigureControlPointStyleProperty.h" namespace mitk { class BaseRenderer; class Contour; /** * \brief OpenGL-based mapper to render display sub-class instances of mitk::PlanarFigure * * The appearance of planar figures can be configured through properties. If no properties are specified, * default values will be used. There are four elements a planar figure consists of: * *
    *
  1. "line": the main line segments of the planar figure (note: text is drawn in the same style) *
  2. "helperline": additional line segments of planar figures, such as arrow tips, arches of angles, etc. *
  3. "outline": background which is drawn behind the lines and helperlines of the planar figure (optional) *
  4. "marker": the markers (control points) of a planar figure *
  5. "markerline": the lines by which markers (control points) are surrounded *
* * In the following, all appearance-related planar figure properties are listed: * *
    *
  1. General properties for the planar figure *
      *
    • "planarfigure.drawoutline": if true, the "outline" lines is drawn *
    • "planarfigure.drawquantities": if true, the quantities (text) associated with the planar figure is drawn *
    • "planarfigure.drawname": if true, the name specified by the dataNode is drawn *
    • "planarfigure.drawshadow": if true, a black shadow is drawn around the planar figure *
    • "planarfigure.controlpointshape": style of the control points (enum) *
    *
  2. Line widths of planar figure elements *
      *
    • "planarfigure.line.width": width of "line" segments (float value, in mm) *
    • "planarfigure.shadow.widthmodifier": the width of the shadow is defined by width of the "line" * this modifier *
    • "planarfigure.outline.width": width of "outline" segments (float value, in mm) *
    • "planarfigure.helperline.width": width of "helperline" segments (float value, in mm) *
    *
  3. Color/opacity of planar figure elements in normal mode (unselected) *
      *
    • "planarfigure.default.line.color" *
    • "planarfigure.default.line.opacity" *
    • "planarfigure.default.outline.color" *
    • "planarfigure.default.outline.opacity" *
    • "planarfigure.default.helperline.color" *
    • "planarfigure.default.helperline.opacity" *
    • "planarfigure.default.markerline.color" *
    • "planarfigure.default.markerline.opacity" *
    • "planarfigure.default.marker.color" *
    • "planarfigure.default.marker.opacity" *
    *
  4. Color/opacity of planar figure elements in hover mode (mouse-over) *
      *
    • "planarfigure.hover.line.color" *
    • "planarfigure.hover.line.opacity" *
    • "planarfigure.hover.outline.color" *
    • "planarfigure.hover.outline.opacity" *
    • "planarfigure.hover.helperline.color" *
    • "planarfigure.hover.helperline.opacity" *
    • "planarfigure.hover.markerline.color" *
    • "planarfigure.hover.markerline.opacity" *
    • "planarfigure.hover.marker.color" *
    • "planarfigure.hover.marker.opacity" *
    *
  5. Color/opacity of planar figure elements in selected mode *
      *
    • "planarfigure.selected.line.color" *
    • "planarfigure.selected.line.opacity" *
    • "planarfigure.selected.outline.color" *
    • "planarfigure.selected.outline.opacity" *
    • "planarfigure.selected.helperline.color" *
    • "planarfigure.selected.helperline.opacity" *
    • "planarfigure.selected.markerline.color;" *
    • "planarfigure.selected.markerline.opacity" *
    • "planarfigure.selected.marker.color" *
    • "planarfigure.selected.marker.opacity" *
    *
* * \ingroup Mapper */ -class PlanarFigure_EXPORT PlanarFigureMapper2D : public GLMapper2D +class PlanarFigure_EXPORT PlanarFigureMapper2D : public GLMapper { public: - mitkClassMacro(PlanarFigureMapper2D, Mapper2D); + mitkClassMacro(PlanarFigureMapper2D, GLMapper); itkNewMacro(Self); /** * reimplemented from Baseclass */ virtual void Paint(BaseRenderer * renderer); static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); protected: enum PlanarFigureDisplayMode { PF_DEFAULT = 0, PF_HOVER = 1, PF_SELECTED = 2, PF_COUNT = 3 //helper variable }; PlanarFigureMapper2D(); virtual ~PlanarFigureMapper2D(); void TransformObjectToDisplay( const mitk::Point2D &point2D, mitk::Point2D &displayPoint, const mitk::Geometry2D *objectGeometry, const mitk::Geometry2D *rendererGeometry, const mitk::DisplayGeometry *displayGeometry ); void DrawMarker( const mitk::Point2D &point, float* lineColor, float lineOpacity, float* markerColor, float markerOpacity, float lineWidth, PlanarFigureControlPointStyleProperty::Shape shape, const mitk::Geometry2D *objectGeometry, const mitk::Geometry2D *rendererGeometry, const mitk::DisplayGeometry *displayGeometry ); void PaintPolyLine( mitk::PlanarFigure::PolyLineType vertices, bool closed, float* color, float opacity, float lineWidth, Point2D& firstPoint, const Geometry2D* planarFigureGeometry2D, const Geometry2D* rendererGeometry2D, const DisplayGeometry* displayGeometry); void DrawMainLines( mitk::PlanarFigure* figure, float* color, float opacity, bool drawShadow, float lineWidth, float shadowWidthFactor, Point2D& firstPoint, const Geometry2D* planarFigureGeometry2D, const Geometry2D* rendererGeometry2D, const DisplayGeometry* displayGeometry) ; void DrawHelperLines( mitk::PlanarFigure* figure, float* color, float opacity, bool drawShadow, float lineWidth, float shadowWidthFactor, Point2D& firstPoint, const Geometry2D* planarFigureGeometry2D, const Geometry2D* rendererGeometry2D, const DisplayGeometry* displayGeometry) ; void InitializeDefaultPlanarFigureProperties(); void InitializePlanarFigurePropertiesFromDataNode( const mitk::DataNode* node ); void SetColorProperty( float property[3][3], PlanarFigureDisplayMode mode, float red, float green, float blue ) { property[mode][0] = red; property[mode][1] = green; property[mode][2] = blue; } void SetFloatProperty( float* property, PlanarFigureDisplayMode mode, float value ) { property[mode] = value; } private: bool m_IsSelected; bool m_IsHovering; bool m_DrawOutline; bool m_DrawQuantities; bool m_DrawShadow; bool m_DrawControlPoints; bool m_DrawName; // the width of the shadow is defined as 'm_LineWidth * m_ShadowWidthFactor' float m_LineWidth; float m_ShadowWidthFactor; float m_OutlineWidth; float m_HelperlineWidth; float m_PointWidth; PlanarFigureControlPointStyleProperty::Shape m_ControlPointShape; float m_LineColor[3][3]; float m_LineOpacity[3]; float m_OutlineColor[3][3]; float m_OutlineOpacity[3]; float m_HelperlineColor[3][3]; float m_HelperlineOpacity[3]; float m_MarkerlineColor[3][3]; float m_MarkerlineOpacity[3]; float m_MarkerColor[3][3]; float m_MarkerOpacity[3]; }; } // namespace mitk #endif /* MITK_PLANAR_FIGURE_MAPPER_2D_H_ */ diff --git a/Modules/Qmitk/Documentation/Doxygen/Modules.dox b/Modules/Qmitk/Documentation/Doxygen/Modules.dox new file mode 100644 index 0000000000..8ad60c754c --- /dev/null +++ b/Modules/Qmitk/Documentation/Doxygen/Modules.dox @@ -0,0 +1,22 @@ +/** + \defgroup QmitkModule Qmitk + \ingroup MITKModules + + \brief Basic Qt widgets and classes for MITK. + + This module provides a set of Qt widgets and classes generally useful for + any MITK application. The main widgets are: + + - QmitkLevelWindowWidget + - QmitkProgressBar + - QmitkRenderWindow + - QmitkStdMultiWidget + + A couple of Qt models for use in the model/view architecture of Qt are also + provided. Among them are: + + - QmitkDataStorageListModel + - QmitkDataStorageTableModel + - QmitkDataStorageTreeModel + - QmitkPropertiesTableModel +*/ diff --git a/Modules/Qmitk/QmitkApplicationCursor.h b/Modules/Qmitk/QmitkApplicationCursor.h index bebfb5ff8c..9742cf7bfe 100644 --- a/Modules/Qmitk/QmitkApplicationCursor.h +++ b/Modules/Qmitk/QmitkApplicationCursor.h @@ -1,47 +1,48 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITK_APPLICATION_CURSOR_H_INCLUDED #define QMITK_APPLICATION_CURSOR_H_INCLUDED #include #include "mitkApplicationCursor.h" /*! + \ingroup QmitkModule \brief Qt specific implementation of ApplicationCursorImplementation This class very simply calls the QApplication's methods setOverrideCursor() and restoreOverrideCursor(). */ class QMITK_EXPORT QmitkApplicationCursor : public mitk::ApplicationCursorImplementation { public: // Will be instantiated automatically from QmitkApplicationCursor.cpp once QmitkApplicationCursor(); virtual void PushCursor(const char* XPM[], int hotspotX, int hotspotY); virtual void PopCursor(); virtual const mitk::Point2I GetCursorPosition(); virtual void SetCursorPosition(const mitk::Point2I&); protected: private: }; #endif diff --git a/Modules/Qmitk/QmitkDataStorageComboBox.h b/Modules/Qmitk/QmitkDataStorageComboBox.h index 9fe0a8c45a..19dfce3897 100644 --- a/Modules/Qmitk/QmitkDataStorageComboBox.h +++ b/Modules/Qmitk/QmitkDataStorageComboBox.h @@ -1,241 +1,242 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkDataStorageComboBox_h #define QmitkDataStorageComboBox_h #include // Own Includes #include "mitkDataStorage.h" #include "mitkDataNode.h" #include "mitkWeakPointer.h" #include "mitkNodePredicateBase.h" // Toolkit Includes #include #include // Forward Declartions /// +/// \ingroup QmitkModule /// \class QmitkDataStorageComboBox /// \author Michael Mueller /// \version 4.0 /// \date 2009-02-09 /// \ingroup Widgets /// \brief Displays all or a subset (defined by a predicate) of nodes of the Data Storage. /// /// Dont forget that this class inherits from QComboBox and you can therefore use the whole API of QComboBox. /// class QMITK_EXPORT QmitkDataStorageComboBox : public QComboBox { //#CLASS-MACROS,FRIENDS Q_OBJECT //#CTORS/DTOR public: /// /// \brief Ctor for an empty combobox. Use setDataStorage and setPredicate afterwards. /// QmitkDataStorageComboBox(QWidget* parent = 0, bool _AutoSelectNewNodes=false); /// /// \brief Ctor for constructing QmitkDataStorageComboBox with given DataStorageComboBox and given _Predicate. /// QmitkDataStorageComboBox( mitk::DataStorage* _DataStorage, const mitk::NodePredicateBase* _Predicate, QWidget* parent = 0, bool _AutoSelectNewNodes=false); /// /// \brief Standard Dtor. Nothing to do here. /// ~QmitkDataStorageComboBox(); /// /// \brief Seaches for a given node and returns a valid index or -1 if the node was not found. /// virtual int Find( const mitk::DataNode* _DataNode ) const; //#PUBLIC GETTER public: /// /// \brief Get the DataStorage this ComboBox listens to. /// mitk::DataStorage::Pointer GetDataStorage() const; /// /// \brief Return the predicate (may be NULL) that is responsible for the _DataNode selection of this ComboBox. /// const mitk::NodePredicateBase::ConstPointer GetPredicate() const; /// /// \brief Returns the _DataNode at Index index or 0 if the index is out of bounds. /// virtual mitk::DataNode::Pointer GetNode(int index) const; /// /// \brief Returns the selected _DataNode or 0 if there is none. /// virtual mitk::DataNode::Pointer GetSelectedNode() const; /// /// \brief Returns all nodes that are stored in this combobox. /// mitk::DataStorage::SetOfObjects::ConstPointer GetNodes() const; /// /// Returns the AutoSelectNewItems. /// \see SetAutoSelectNewItems /// virtual bool GetAutoSelectNewItems(); //#PUBLIC SETTER public: /// /// \brief Set the DataStorage this ComboBox should listen to. /// /// If DataStorage is 0 nothing will be shown. If DataStorage is re-set the combobox will be resetted. void SetDataStorage(mitk::DataStorage* dataStorage); /// /// \brief Set the predicate for this ComboBox. (QmitkDataStorageComboBox is now owner of the predicate) /// /// If predicate is NULL all nodes will be selected. If predicate changes the whole combobox will be resetted. void SetPredicate(const mitk::NodePredicateBase* _Predicate); /// /// Adds a node to the ComboBox. Gets called everytime a DataStorage Add Event was thrown. /// virtual void AddNode(const mitk::DataNode* _DataNode); /// /// Removes a node from the ComboBox at a specified index (if the index exists). Gets called when a DataStorage Remove Event was thrown. /// virtual void RemoveNode(int index); /// /// Removes a node from the ComboBox. Gets called when a DataStorage Remove Event was thrown. /// virtual void RemoveNode(const mitk::DataNode* _DataNode); /// /// Set a _DataNode in the ComboBox at the specified index (if the index exists). /// Internally the method just calls RemoveNode(unsigned int) /// virtual void SetNode(int index, const mitk::DataNode* _DataNode); /// /// Replaces a _DataNode in the combobox by an _OtherDataNode. /// Internally the method just calls SetNode(unsigned int, mitk::DataNode*) /// virtual void SetNode(const mitk::DataNode* _DataNode, const mitk::DataNode* _OtherDataNode); /// /// Sets AutoSelectNewItems flag. If set to true new Nodes will be automatically selected. Default is false. /// virtual void SetAutoSelectNewItems(bool _AutoSelectNewItems); /// /// \brief Called when a node is deleted or the name property of the node was modified. Calls RemoveNode or SetNode then. /// virtual void OnDataNodeDeleteOrModified(const itk::Object *caller, const itk::EventObject &event); signals: /// /// \brief Throw a signal when the _DataNode selection changed. /// void OnSelectionChanged(const mitk::DataNode*); //#PROTECTED GETTER protected: /// /// \brief Checks if the given index is within the range of the m_Nodes vector. /// bool HasIndex(unsigned int index) const; //#PROTECTED SETTER protected slots: /// /// \brief Slot for signal when the user selects another item. /// void OnCurrentIndexChanged(int); //#PUBLIC SETTER public slots: /// /// \brief Slot for signal when user wants to set a node as current selected node. /// void SetSelectedNode(mitk::DataNode::Pointer item); protected: /// /// \brief Inserts a new node at the given index. If the index does not exist, the _DataNode is simply appended to the combobox. /// /// This function is used by AddNode() and SetNode() because they just to the same: /// 1. If node is replaced (that is when index exists), /// the itk::Event observer will be removed /// 2. Check Node against Predicate /// 3. Register for itk::Events on the node /// 4. Insert Node and show in combobox virtual void InsertNode(int index, const mitk::DataNode* _DataNode); /// /// \brief Init-function this class with the given dataStorage and _Predicate. This function is called by all ctors. /// void Init(); /// /// \brief Reset function whenever datastorage or predicate changes. /// virtual void Reset(); protected: //#PROTECTED MEMBER VARS /// /// Pointer to the DataStorage from which the nodes are selected (remember: in BlueBerry there /// might be more than one DataStorage). /// mitk::WeakPointer m_DataStorage; /// /// \brief Holds the predicate that is responsible for the _DataNode selection of this ComboBox. /// If the predicate is 0, every _DataNode will be selected. /// mitk::NodePredicateBase::ConstPointer m_Predicate; /// /// Holds all selected Nodes. Dont hold smart pointer as we are in a GUI class. /// std::vector m_Nodes; /// /// \brief Holds the tags of the node-modified observers. (must be updated everytime m_Nodes changes) /// std::vector m_NodesModifiedObserverTags; /// /// \brief Holds the tags of the node-modified observers. (must be updated everytime m_Nodes changes) /// std::vector m_NodesDeleteObserverTags; /// /// \brief Maps a a specific node to (Name-)property. This is needed because we have to find the assiociated node /// whenever the name property of a node changed. /// std::map m_PropertyToNode; /// /// \brief Event function guard. Each function which is called by an event mechanism /// first checks if this is true in order to avoid endless loops. bool m_BlockEvents; /// /// \brief If set to "true" new Nodes will be automatically selected. bool m_AutoSelectNewNodes; }; #endif // QmitkDataStorageComboBox_h diff --git a/Modules/Qmitk/QmitkDataStorageListModel.h b/Modules/Qmitk/QmitkDataStorageListModel.h index 44a7c55697..8fbf016e3b 100755 --- a/Modules/Qmitk/QmitkDataStorageListModel.h +++ b/Modules/Qmitk/QmitkDataStorageListModel.h @@ -1,125 +1,126 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKDATASTORAGELISTMODEL_H_ #define QMITKDATASTORAGELISTMODEL_H_ #include //# Own includes // mitk #include "mitkDataStorage.h" #include "mitkNodePredicateBase.h" // Qmitk //# Toolkit includes // Qt #include // stl #include +/// \ingroup QmitkModule class QMITK_EXPORT QmitkDataStorageListModel: public QAbstractListModel { public: //# Ctors / Dtor /// /// The NodePredicate is owned by the model /// QmitkDataStorageListModel(mitk::DataStorage::Pointer dataStorage = 0, mitk::NodePredicateBase* pred = 0, QObject* parent = 0); ~QmitkDataStorageListModel(); //# Getter / Setter void SetDataStorage(mitk::DataStorage::Pointer dataStorage); mitk::DataStorage::Pointer GetDataStorage() const; void SetPredicate(mitk::NodePredicateBase* pred); mitk::NodePredicateBase* GetPredicate() const; std::vector GetDataNodes() const; mitk::DataNode::Pointer getNode(const QModelIndex &index) const; //# From QAbstractListModel Qt::ItemFlags flags(const QModelIndex& index) const; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; int rowCount(const QModelIndex& parent = QModelIndex()) const; /// /// Called when a DataStorage Add Event was thrown. May be reimplemented /// by deriving classes. /// virtual void NodeAdded(const mitk::DataNode* node); /// /// Called when a DataStorage Remove Event was thrown. May be reimplemented /// by deriving classes. /// virtual void NodeRemoved(const mitk::DataNode* node); /// /// \brief Called when a itk::Object that is hold as a member variable was /// modified in order to react to it. /// virtual void OnModified(const itk::Object *caller, const itk::EventObject &event); /// /// \brief Called when a itk::Object that is hold as a member variable is about to be /// deleted in order to react to it. /// virtual void OnDelete(const itk::Object *caller, const itk::EventObject &event); protected: /// /// \brief Resets the whole model. Get all nodes matching the predicate from the data storage. /// void reset(); /// /// Holds the predicate that defines this SubSet of Nodes. If m_Predicate /// is NULL all Nodes will be selected. *Attention: this class owns the predicate and deletes it* /// mitk::NodePredicateBase::Pointer m_NodePredicate; /// /// Pointer to the DataStorage from which the nodes are selected (remember: in BlueBerry there /// might be more than one DataStorage). /// mitk::DataStorage* m_DataStorage; /// /// \brief Holds the tag of the datastorage-delete observer. /// unsigned long m_DataStorageDeleteObserverTag; /// /// Holds all selected Nodes. Dont hold smart pointer as we are in a GUI class. /// std::vector m_DataNodes; /// /// \brief Holds the tags of the node-modified observers. /// std::vector m_DataNodesModifiedObserversTags; /// /// Saves if this model is currently working on events to prevent endless event loops. /// bool m_BlockEvents; }; #endif /* QMITKDATASTORAGELISTMODEL_H_ */ diff --git a/Modules/Qmitk/QmitkDataStorageTableModel.h b/Modules/Qmitk/QmitkDataStorageTableModel.h index 3c511bd747..fac0b03a69 100644 --- a/Modules/Qmitk/QmitkDataStorageTableModel.h +++ b/Modules/Qmitk/QmitkDataStorageTableModel.h @@ -1,228 +1,229 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkDataStorageTableModel_h #define QmitkDataStorageTableModel_h #include /// Own includes. #include "mitkDataStorage.h" #include "mitkBaseProperty.h" #include "mitkWeakPointer.h" #include "mitkNodePredicateBase.h" /// Toolkit includes. #include /// Forward declarations. /// +/// \ingroup QmitkModule /// \class QmitkDataStorageTableModel /// /// \brief A table model for a set of DataNodes defined by a predicate. /// \TODO make columns interchangeable, select which properties to show as columns /// class QMITK_EXPORT QmitkDataStorageTableModel : public QAbstractTableModel { Q_OBJECT //#Ctors/Dtor public: /// /// Constructs a new QmitkDataStorageTableModel and sets a predicate that defines /// this list. /// \see setPredicate() /// QmitkDataStorageTableModel(mitk::DataStorage::Pointer _DataStorage, mitk::NodePredicateBase* _Predicate = 0 , QObject* parent = 0 ); /// /// Standard dtor. Delete predicate, disconnect from DataStorage. /// virtual ~QmitkDataStorageTableModel(); //# Public GETTER public: /// /// Get the DataStorage. /// const mitk::DataStorage::Pointer GetDataStorage() const; /// /// Get the predicate. /// mitk::NodePredicateBase::Pointer GetPredicate() const; /// /// Get node at a specific model index. Another way to implement this, is /// by introducing a new role like "DateTreeNode" and capture /// that in the data function. /// mitk::DataNode::Pointer GetNode(const QModelIndex &index) const; /// /// Overridden from QAbstractTableModel. Returns the header data at section /// for given orientation and role. /// virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; /// /// Overridden from QAbstractTableModel. Returns what can be done /// with an item. /// virtual Qt::ItemFlags flags(const QModelIndex &index) const; /// /// Overridden from QAbstractTableModel. Returns the node count. /// virtual int rowCount(const QModelIndex &parent) const; /// /// Overridden from QAbstractTableModel. Returns the number of features (columns) to display. /// virtual int columnCount(const QModelIndex &parent) const; /// /// Overridden from QAbstractTableModel. Returns the data at index for given role. /// virtual QVariant data(const QModelIndex &index, int role) const; //# Public SETTERS public: /// /// Sets the DataStorage. /// void SetDataStorage(mitk::DataStorage::Pointer _DataStorage); /// /// Sets the predicate. QmitkDataStorageTableModel is owner of the predicate! /// void SetPredicate(mitk::NodePredicateBase* _Predicate); /// /// Adds a node to this model. /// There are two constraints for nodes in this model: /// 1. If a predicate is set (not null) the node will be checked against it. /// 2. The node has to have a data object (no one wants to see empty nodes). /// Also adds event listeners to the node. /// virtual void AddNode(const mitk::DataNode* node); /// /// Removes a node from this model. Also removes any event listener from the node. /// virtual void RemoveNode(const mitk::DataNode* node); /// /// Returns a copy of the node-vector that is shown by this model /// virtual std::vector GetNodeSet() const; /// /// \brief Called when a single property was changed. /// The function searches through the list of nodes in this model for the changed /// property. If the property was found a dataChanged signal is emitted forcing /// all observing views to request the data again. /// virtual void PropertyModified(const itk::Object *caller, const itk::EventObject &event); /// /// Overridden from QAbstractTableModel. Sets data at index for given role. /// bool setData(const QModelIndex &index, const QVariant &value, int role); /// /// \brief Reimplemented sort function from QAbstractTableModel to enable sorting on the table. /// void sort ( int column, Qt::SortOrder order = Qt::AscendingOrder ); //#PROTECTED INNER CLASSES protected: /// /// \struct DataNodeCompareFunction /// \brief A struct that inherits from std::binary_function. You can use it in std::sort algorithm for sorting the node list elements. /// struct DataNodeCompareFunction : public std::binary_function { /// /// \brief Specifies field of the property with which it will be sorted. /// enum CompareCriteria { CompareByName = 0, CompareByClassName, CompareByVisibility }; /// /// \brief Specifies Ascending/descending ordering. /// enum CompareOperator { Less = 0, Greater }; /// /// \brief Creates a PropertyDataSetCompareFunction. A CompareCriteria and a CompareOperator must be given. /// DataNodeCompareFunction(CompareCriteria _CompareCriteria = CompareByName, CompareOperator _CompareOperator = Less); /// /// \brief The reimplemented compare function. /// bool operator()(const mitk::DataNode::Pointer& _Left , const mitk::DataNode::Pointer& _Right) const; protected: CompareCriteria m_CompareCriteria; CompareOperator m_CompareOperator; }; //#Protected SETTER protected: /// /// Called when DataStorage or Predicate changed. Resets whole model and reads all nodes /// in again. /// virtual void Reset(); //#Protected MEMBER VARIABLES protected: /// /// Pointer to the DataStorage from which the nodes are selected (remember: in BlueBerry there /// might be more than one DataStorage). /// Store it in a weak pointer. This is a GUI class which should not hold a strong reference /// to any non-GUI Object. /// mitk::WeakPointer m_DataStorage; /// /// Holds the predicate that defines this SubSet of Nodes. If m_Predicate /// is NULL all Nodes will be selected. /// mitk::NodePredicateBase::Pointer m_Predicate; /// /// Holds all selected Nodes. /// std::vector m_NodeSet; /// /// \brief Maps a property to an observer tag. /// std::map m_NamePropertyModifiedObserverTags; /// /// \brief Maps a property to an observer tag. /// std::map m_VisiblePropertyModifiedObserverTags; /// /// Saves if this model is currently working on events to prevent endless event loops. /// bool m_BlockEvents; /// /// \brief The property is true when the property list is sorted in descending order. /// bool m_SortDescending; }; #endif diff --git a/Modules/Qmitk/QmitkDataStorageTreeModel.h b/Modules/Qmitk/QmitkDataStorageTreeModel.h index 7cbf6c87b3..fc3674964a 100644 --- a/Modules/Qmitk/QmitkDataStorageTreeModel.h +++ b/Modules/Qmitk/QmitkDataStorageTreeModel.h @@ -1,292 +1,293 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKDATASTORAGETREEMODEL_H_ #define QMITKDATASTORAGETREEMODEL_H_ #include #include #include #include #include #include "QmitkEnums.h" #include "QmitkCustomVariants.h" #include #include #include +/// \ingroup QmitkModule class QMITK_EXPORT QmitkDataStorageTreeModel : public QAbstractItemModel { //# CONSTANTS,TYPEDEFS public: static const std::string COLUMN_NAME; static const std::string COLUMN_TYPE; static const std::string COLUMN_VISIBILITY; //# CTORS,DTOR public: QmitkDataStorageTreeModel(mitk::DataStorage* _DataStorage , bool _PlaceNewNodesOnTop=false , bool _ShowHelperObjects=false , bool _ShowNodesContainingNoData=false , QObject* parent = 0); ~QmitkDataStorageTreeModel(); //# GETTER public: typedef std::map NodeTagMapType; /// /// Get node at a specific model index. /// This function is used to get a node from a QModelIndex /// mitk::DataNode::Pointer GetNode(const QModelIndex &index) const; /// /// Returns a copy of the node-vector that is shown by this model /// virtual QList GetNodeSet() const; /// /// Get the DataStorage. /// const mitk::DataStorage::Pointer GetDataStorage() const; /// /// Get the top placement flag /// bool GetPlaceNewNodesOnTopFlag() { return m_PlaceNewNodesOnTop; } /// /// Get the helper object visibility flag /// bool GetShowHelperObjectsFlag() { return m_ShowHelperObjects; } /// /// Get the visibility flag for showing nodes that contain no data /// bool GetShowNodesContainingNoDataFlag() { return m_ShowNodesContainingNoData; } /// /// Set the top placement flag /// void SetPlaceNewNodesOnTop(bool _PlaceNewNodesOnTop); //# (Re-)implemented from QAbstractItemModel //# Read model Qt::ItemFlags flags(const QModelIndex& index) const; QVariant data ( const QModelIndex & index, int role = Qt::DisplayRole ) const; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; int rowCount ( const QModelIndex & parent = QModelIndex() ) const; int columnCount ( const QModelIndex & parent = QModelIndex() ) const; //# hierarchical model /// /// called whenever the model or the view needs to create a QModelIndex for a particular /// child item (or a top-level item if parent is an invalid QModelIndex) /// QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const; QModelIndex parent ( const QModelIndex & index ) const; //# editable model bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole); bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); Qt::DropActions supportedDropActions() const; Qt::DropActions supportedDragActions() const; QStringList mimeTypes() const; QMimeData * mimeData(const QModelIndexList & indexes) const; //# End of QAbstractItemModel //# SETTER public: /// /// Sets the DataStorage. The whole model will be resetted. /// void SetDataStorage(mitk::DataStorage* _DataStorage); /// /// Notify that the DataStorage was deleted. The whole model will be resetted. /// void SetDataStorageDeleted(const itk::Object* _DataStorage); /// /// Adds a node to this model. /// If a predicate is set (not null) the node will be checked against it.The node has to have a data object (no one wants to see empty nodes). /// virtual void AddNode(const mitk::DataNode* node); /// /// Removes a node from this model. Also removes any event listener from the node. /// virtual void RemoveNode(const mitk::DataNode* node); /// /// Sets a node to modfified. Called by the DataStorage /// virtual void SetNodeModified(const mitk::DataNode* node); /// /// \return an index for the given datatreenode in the tree. If the node is not found /// QModelIndex GetIndex(const mitk::DataNode*) const; /// /// Show or hide helper objects /// void SetShowHelperObjects(bool _ShowHelperObjects); /// /// Show or hide objects that contain no data /// void SetShowNodesContainingNoData(bool _ShowNodesContainingNoData); /// /// Update the visibility of data nodes according to the preference settings /// void UpdateNodeVisibility(); //# MISC protected: /// /// Helper class to represent a tree structure of DataNodes /// class TreeItem { public: /// /// Constructs a new TreeItem with the given DataNode (must not be 0) /// TreeItem(mitk::DataNode* _DataNode, TreeItem* _Parent=0); /// /// Removes itself as child from its parent-> Does not delete its children /// \sa Delete() /// virtual ~TreeItem(); /// /// Find the index of an item /// int IndexOfChild(const TreeItem* item) const; /// /// \child The child at pos index or 0 if it not exists /// TreeItem* GetChild(int index) const; /// /// Find the TreeItem containing a special tree node (recursive tree function) /// TreeItem* Find( const mitk::DataNode* _DataNode) const; /// /// Get the amount of children /// int GetChildCount() const; /// /// \return the index of this node in its parent list /// int GetIndex() const; /// /// \return the parent of this tree item /// TreeItem* GetParent() const; /// /// Return the DataNode associated with this node /// mitk::DataNode::Pointer GetDataNode() const; /// /// Get all children as vector /// std::vector GetChildren() const; /// /// add another item as a child of this (only if not already in that list) /// void AddChild( TreeItem* item); /// /// remove another item as child from this /// void RemoveChild( TreeItem* item); /// /// inserts a child at the given position. if pos is not in range /// the element is added at the end /// void InsertChild( TreeItem* item, int index=-1 ); /// Sets the parent on the treeitem void SetParent(TreeItem* _Parent); /// /// Deletes the whole tree branch /// void Delete(); protected: TreeItem* m_Parent; std::vector m_Children; mitk::DataNode::Pointer m_DataNode; }; /// /// Adjusts the LayerProperty according to the nodes position /// void AdjustLayerProperty(); /// /// invoked after m_DataStorage or m_Predicate changed /// TreeItem* TreeItemFromIndex(const QModelIndex &index) const; /// /// Gives a ModelIndex for the Tree Item /// QModelIndex IndexFromTreeItem(TreeItem*) const; /// /// Returns the first element in the nodes sources list (if available) or 0 /// mitk::DataNode* GetParentNode(const mitk::DataNode* node) const; /// /// Adds all Childs in parent to vec. Before a child is added the function is called recursively /// void TreeToVector(TreeItem* parent, std::vector& vec) const; /// /// Adds all Childs in parent to vec. Before a child is added the function is called recursively /// void TreeToNodeSet(TreeItem* parent, QList &vec) const; /// /// Update Tree Model according to predicates /// void Update(); //# ATTRIBUTES protected: mitk::WeakPointer m_DataStorage; mitk::NodePredicateBase::Pointer m_Predicate; bool m_PlaceNewNodesOnTop; bool m_ShowHelperObjects; bool m_ShowNodesContainingNoData; TreeItem* m_Root; NodeTagMapType m_HelperObjectObserverTags; private: void AddNodeInternal(const mitk::DataNode*); void RemoveNodeInternal(const mitk::DataNode*); /// /// Checks if dicom properties patient name, study names and series name exists /// bool DicomPropertiesExists(const mitk::DataNode&) const; }; #endif /* QMITKDATASTORAGETREEMODEL_H_ */ diff --git a/Modules/Qmitk/QmitkEnums.h b/Modules/Qmitk/QmitkEnums.h index b3b0bc73a5..ea1d7b9714 100755 --- a/Modules/Qmitk/QmitkEnums.h +++ b/Modules/Qmitk/QmitkEnums.h @@ -1,27 +1,28 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKENUMS_H_ #define QMITKENUMS_H_ +/// \ingroup QmitkModule enum QmitkItemModelRole { QmitkDataNodeRole = 64, QmitkDataNodeRawPointerRole = 65 }; #endif /* QMITKENUMS_H_ */ diff --git a/Modules/Qmitk/QmitkEventAdapter.h b/Modules/Qmitk/QmitkEventAdapter.h index 01cd98d741..6b6cc67622 100644 --- a/Modules/Qmitk/QmitkEventAdapter.h +++ b/Modules/Qmitk/QmitkEventAdapter.h @@ -1,37 +1,44 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKEVENTADAPTER_H_ #define QMITKEVENTADAPTER_H_ #include #include #include #include #include #include +/** + * \ingroup QmitkModule + * \deprecatedSince{2013_03} mitk::QmitkEventAdapter is deprecated. It will become + * obsolete. Adaption of events is now handeled (for Qt events) in QmitkRenderWindow. + * Refer to \see DataInteractionPage for general information about the concept of + * the new implementation + */ class QMITK_EXPORT QmitkEventAdapter { public: static mitk::MouseEvent AdaptMouseEvent(mitk::BaseRenderer* sender, QMouseEvent* mouseEvent); static mitk::WheelEvent AdaptWheelEvent(mitk::BaseRenderer* sender, QWheelEvent* wheelEvent); static mitk::KeyEvent AdaptKeyEvent(mitk::BaseRenderer* sender, QKeyEvent* keyEvent, const QPoint& point); }; #endif /*QMITKEVENTADAPTER_H_*/ diff --git a/Modules/Qmitk/QmitkLevelWindowPresetDefinitionDialog.h b/Modules/Qmitk/QmitkLevelWindowPresetDefinitionDialog.h index 03dbf06296..5ce80e4a7c 100644 --- a/Modules/Qmitk/QmitkLevelWindowPresetDefinitionDialog.h +++ b/Modules/Qmitk/QmitkLevelWindowPresetDefinitionDialog.h @@ -1,107 +1,108 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKLEVELWINDOWPRESETDEFINITIONDIALOG_H_ #define QMITKLEVELWINDOWPRESETDEFINITIONDIALOG_H_ #include #include "ui_QmitkLevelWindowPresetDefinition.h" #include #include #include #include +/// \ingroup QmitkModule class QMITK_EXPORT QmitkLevelWindowPresetDefinitionDialog : public QDialog, public Ui::QmitkLevelWindowPresetDefinition { Q_OBJECT public: QmitkLevelWindowPresetDefinitionDialog(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkLevelWindowPresetDefinitionDialog(); void setPresets(std::map& level, std::map& window, QString initLevel, QString initWindow); std::map getLevelPresets(); std::map getWindowPresets(); protected slots: void addPreset(); void removePreset(); void changePreset(); void ListViewSelectionChanged(const QItemSelection&, const QItemSelection&); void sortPresets(int index); protected: class PresetTableModel : public QAbstractTableModel { public: struct Entry { std::string name; double level; double window; Entry(const std::string& n, double l, double w) : name(n), level(l), window(w) {} }; PresetTableModel(std::map& levels, std::map& windows, QObject* parent = 0); int rowCount(const QModelIndex&) const; int columnCount(const QModelIndex&) const; QVariant data(const QModelIndex& index, int) const; QVariant headerData(int section, Qt::Orientation orientation, int) const; void addPreset(std::string& name, double level, double window); void removePreset(const QModelIndex&); void changePreset(int row, std::string& name, double level, double window); void getLevels(std::map& levels); void getWindows(std::map& windows); bool contains(std::string& name); Entry getPreset(const QModelIndex&) const; private: std::vector m_Entries; }; void resizeEvent(QResizeEvent* event); void showEvent(QShowEvent* event); void resizeColumns(); PresetTableModel* m_TableModel; QSortFilterProxyModel m_SortModel; }; #endif /*QMITKLEVELWINDOWPRESETDEFINITIONDIALOG_H_*/ diff --git a/Modules/Qmitk/QmitkLevelWindowRangeChangeDialog.h b/Modules/Qmitk/QmitkLevelWindowRangeChangeDialog.h index 1092ff707a..1de4adab8e 100644 --- a/Modules/Qmitk/QmitkLevelWindowRangeChangeDialog.h +++ b/Modules/Qmitk/QmitkLevelWindowRangeChangeDialog.h @@ -1,48 +1,49 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKLEVELWINDOWRANGECHANGEDIALOG_H_ #define QMITKLEVELWINDOWRANGECHANGEDIALOG_H_ #include #include "ui_QmitkLevelWindowRangeChange.h" #include +/// \ingroup QmitkModule class QMITK_EXPORT QmitkLevelWindowRangeChangeDialog : public QDialog, public Ui::QmitkLevelWindowRangeChange { Q_OBJECT public: QmitkLevelWindowRangeChangeDialog(QWidget* parent = 0, Qt::WindowFlags f = 0); int getLowerLimit(); int getUpperLimit(); void setLowerLimit( int rangeMin ); void setUpperLimit( int rangeMax ); protected slots: void inputValidator(); }; #endif /*QMITKLEVELWINDOWRANGECHANGEDIALOG_H_*/ diff --git a/Modules/Qmitk/QmitkLevelWindowWidget.h b/Modules/Qmitk/QmitkLevelWindowWidget.h index 7d2724a3a2..052081690e 100644 --- a/Modules/Qmitk/QmitkLevelWindowWidget.h +++ b/Modules/Qmitk/QmitkLevelWindowWidget.h @@ -1,40 +1,41 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKLEVELWINDOWWIDGET_H_ #define QMITKLEVELWINDOWWIDGET_H_ #include #include "ui_QmitkLevelWindowWidget.h" #include +/// \ingroup QmitkModule class QMITK_EXPORT QmitkLevelWindowWidget : public QWidget, public Ui::QmitkLevelWindow { Q_OBJECT public: QmitkLevelWindowWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); mitk::LevelWindowManager* GetManager(); public slots: void SetDataStorage( mitk::DataStorage* ds ); protected: //unsigned long m_ObserverTag; mitk::LevelWindowManager::Pointer m_Manager; }; #endif /*QMITKLEVELWINDOWWIDGET_H_*/ diff --git a/Modules/Qmitk/QmitkLevelWindowWidgetContextMenu.h b/Modules/Qmitk/QmitkLevelWindowWidgetContextMenu.h index 268a736ea0..0ea3acd554 100644 --- a/Modules/Qmitk/QmitkLevelWindowWidgetContextMenu.h +++ b/Modules/Qmitk/QmitkLevelWindowWidgetContextMenu.h @@ -1,120 +1,120 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKLEVELWINDOWWIDGETCONTEXTMENU_H #define QMITKLEVELWINDOWWIDGETCONTEXTMENU_H #include #include #include #include /** - \class QmitkLevelWindowWidgetContextMenu QmitkLevelWindowWidgetContextMenu.h QmitkLevelWindowWidgetContextMenu.h - \ingroup Widgets - - \brief Provides a contextmenu for Level/Window functionality. Either creates a new contextmenu with standard functions or adds Level/Window standard functions to an predefined contextmenu. - - */ - + * \ingroup QmitkModule + * \brief Provides a contextmenu for Level/Window functionality. + * + * Either creates + * a new contextmenu with standard functions or adds Level/Window standard + * functions to an predefined contextmenu. + */ class QMITK_EXPORT QmitkLevelWindowWidgetContextMenu : public QWidget { Q_OBJECT public: /// constructor QmitkLevelWindowWidgetContextMenu(QWidget * parent, Qt::WindowFlags f = 0 ); virtual ~QmitkLevelWindowWidgetContextMenu(); /*! * data structure which reads and writes presets defined in a XML-file */ mitk::LevelWindowPreset* m_LevelWindowPreset; /*! * data structure which stores the values manipulated * by a QmitkLevelWindowWidgetContextMenu */ mitk::LevelWindow m_LevelWindow; /// submenu with all presets for contextmenu QMenu* m_PresetSubmenu; /// submenu with all images for contextmenu QMenu* m_ImageSubmenu; /// pointer to the object which manages all Level/Window changes on images and holds the LevelWindowProperty /// of the current image mitk::LevelWindowManager* m_Manager; /// map to hold all image-properties, one can get the image which is selected in the contextmenu /// with the QAction representing the image for the contextmenu std::map m_Images; /*! * returns the contextmenu with standard functions for Level/Window * * input is a prefilled contextmenu to which standard functions will be added */ void getContextMenu(QMenu* contextmenu); /// returns the contextmenu with standard functions for Level/Window void getContextMenu(); /// lets this object know about the LevelWindowManager to get all images and tell about changes void setLevelWindowManager(mitk::LevelWindowManager* levelWindowManager); protected: /// ID of preset selected in contextmenu QAction* m_PresetAction; /// ID of image selected in contextmenu QAction* m_ImageAction; protected slots: /// sets level and window value of the current image to the values defined for the selected preset void setPreset(QAction* presetAction); /// calls the mitkLevelWindow SetAuto method with guessByCentralSlice false, so that the greyvalues from whole image will be considered void useAllGreyvaluesFromImage(); /// sets the level window slider to be fixed void setFixed(); /// adds a new Preset for presets-contextmenu void addPreset(); /// resets the current images Level/Window to its default values void setDefaultLevelWindow(); /// resets the current images scalerange to its default values void setDefaultScaleRange(); /// changes the current images scalerange void changeScaleRange(); /// sets the selected image or the topmost layer image to the new current image void setImage(QAction* imageAction); /// sets the window to its maximum Size to fit the scalerange void setMaximumWindow(); }; #endif diff --git a/Modules/Qmitk/QmitkLineEditLevelWindowWidget.h b/Modules/Qmitk/QmitkLineEditLevelWindowWidget.h index a226d086af..329b38f4ad 100644 --- a/Modules/Qmitk/QmitkLineEditLevelWindowWidget.h +++ b/Modules/Qmitk/QmitkLineEditLevelWindowWidget.h @@ -1,102 +1,100 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKLINEEDITLEVELWINDOWWIDGET #define QMITKLINEEDITLEVELWINDOWWIDGET #include #include #include class QmitkLevelWindowWidgetContextMenu; class QLineEdit; /** - \class QmitkLineEditLevelWindowWidget QmitkLineEditLevelWindowWidget.h QmitkLineEditLevelWindowWidget.h - \ingroup Widgets - - \brief Provides a widget with two lineedit fields, one to change the window value of the current image and one to change the level value of the current image. - - */ - + * \ingroup QmitkModule + * \brief Provides a widget with two lineedit fields, one to change the + * window value of the current image and one to change the level value of + * the current image. + */ class QMITK_EXPORT QmitkLineEditLevelWindowWidget : public QWidget { Q_OBJECT public: /// constructor QmitkLineEditLevelWindowWidget( QWidget * parent = 0, Qt::WindowFlags f = 0 ); /// destructor ~QmitkLineEditLevelWindowWidget(); /// inputfield for level value QLineEdit* m_LevelInput; /// inputfield for window value QLineEdit* m_WindowInput; /*! * data structure which stores the values manipulated * by a QmitkLineEditLevelWindowWidget */ mitk::LevelWindow m_LevelWindow; /// manager who is responsible to collect and deliver changes on Level/Window mitk::LevelWindowManager::Pointer m_Manager; /// sets the manager who is responsible to collect and deliver changes on Level/Window void setLevelWindowManager(mitk::LevelWindowManager* levelWindowManager); /// sets the DataStorage which holds all image-nodes void SetDataStorage( mitk::DataStorage* ds ); /// returns the manager who is responsible to collect and deliver changes on Level/Window mitk::LevelWindowManager* GetManager(); private: /// creates the contextmenu for this widget from class QmitkLevelWindowWidgetContextMenu void contextMenuEvent ( QContextMenuEvent * ); /// change notifications from the mitkLevelWindowManager void OnPropertyModified(const itk::EventObject& e); public slots: /// called when return is pressed in levelinput field void SetLevelValue(); /// called when return is pressed in windowinput field void SetWindowValue(); // validator to accept only possible values for Level/Window in lineedits //void setValidator(); protected: unsigned long m_ObserverTag; bool m_IsObserverTagSet; /*! * data structure which creates the contextmenu for QmitkLineEditLevelWindowWidget */ QmitkLevelWindowWidgetContextMenu* m_Contextmenu; }; #endif // QMITKLINEEDITLEVELWINDOWWIDGET diff --git a/Modules/Qmitk/QmitkMemoryUsageIndicatorView.h b/Modules/Qmitk/QmitkMemoryUsageIndicatorView.h index 56ad1bb829..72e7df3de6 100644 --- a/Modules/Qmitk/QmitkMemoryUsageIndicatorView.h +++ b/Modules/Qmitk/QmitkMemoryUsageIndicatorView.h @@ -1,54 +1,55 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKMEMORYUSAGEINDICATORVIEW_WIDGET #define QMITKMEMORYUSAGEINDICATORVIEW_WIDGET #include #include #include #include "ui_QmitkMemoryUsageIndicator.h" +/// \ingroup QmitkModule class QMITK_EXPORT QmitkMemoryUsageIndicatorView : public QWidget, public Ui::QmitkMemoryUsageIndicator { Q_OBJECT public: /// constructor QmitkMemoryUsageIndicatorView( QWidget * parent=0, Qt::WindowFlags f = 0 ); /// destructor ~QmitkMemoryUsageIndicatorView(); protected slots: void UpdateMemoryUsage(); protected: std::string FormatMemorySize( size_t size ); std::string FormatPercentage( double val ); std::string GetMemoryDescription( size_t processSize, float percentage ); QPixmap m_LEDGreen; QPixmap m_LEDYellow; QPixmap m_LEDOrange; QPixmap m_LEDRed; char m_PreviousState; }; #endif //QMITKMEMORYUSAGEINDICATORVIEW_WIDGET diff --git a/Modules/Qmitk/QmitkMouseModeSwitcher.h b/Modules/Qmitk/QmitkMouseModeSwitcher.h index 5f94bf2304..5e53b5e6e1 100644 --- a/Modules/Qmitk/QmitkMouseModeSwitcher.h +++ b/Modules/Qmitk/QmitkMouseModeSwitcher.h @@ -1,86 +1,87 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkMouseModeSwitcher_h #define QmitkMouseModeSwitcher_h #include "QmitkExports.h" #include "mitkMouseModeSwitcher.h" #include /** - \brief Qt toolbar representing mitk::MouseModeSwitcher. - - Provides buttons for the interaction modes defined in mitk::MouseModeSwitcher - and communicates with this non-graphical class. - - Can be used in a GUI to provide a mouse mode selector to the user. -*/ + * \ingroup QmitkModule + * \brief Qt toolbar representing mitk::MouseModeSwitcher. + * + * Provides buttons for the interaction modes defined in mitk::MouseModeSwitcher + * and communicates with this non-graphical class. + * + * Can be used in a GUI to provide a mouse mode selector to the user. + */ class QMITK_EXPORT QmitkMouseModeSwitcher : public QToolBar { Q_OBJECT public: QmitkMouseModeSwitcher( QWidget* parent = 0 ); virtual ~QmitkMouseModeSwitcher(); typedef mitk::MouseModeSwitcher::MouseMode MouseMode; public slots: /** \brief Connect to non-GUI class. When a button is pressed, given mitk::MouseModeSwitcher is informed to adapt interactors. \todo QmitkMouseModeSwitcher could be enhanced to actively observe mitk::MouseModeSwitcher and change available actions or visibility appropriately. */ void setMouseModeSwitcher( mitk::MouseModeSwitcher* ); signals: /** \brief Mode activated. This signal is needed for other GUI element to react appropriately. Sadly this is needed to provide "normal" functionality of QmitkStdMultiWidget, because this must enable/disable automatic reaction of SliceNavigationControllers to mouse clicks - depending on which mode is active. */ void MouseModeSelected(mitk::MouseModeSwitcher::MouseMode id); // TODO change int to enum of MouseModeSwitcher protected slots: void modeSelectedByUser(); void addButton( MouseMode id, const QString& toolName, const QIcon& icon, bool on = false ); // TODO change int to enum of MouseModeSwitcher protected: void OnMouseModeChanged(const itk::EventObject&); QActionGroup* m_ActionGroup; mitk::MouseModeSwitcher* m_MouseModeSwitcher; unsigned long m_ObserverTag; bool m_InObservationReaction; }; #endif diff --git a/Modules/Qmitk/QmitkNodeDescriptor.h b/Modules/Qmitk/QmitkNodeDescriptor.h index 6a01aae666..8eda6004ed 100644 --- a/Modules/Qmitk/QmitkNodeDescriptor.h +++ b/Modules/Qmitk/QmitkNodeDescriptor.h @@ -1,101 +1,102 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkNodeDescriptor_h #define QmitkNodeDescriptor_h #include #include #include "mitkDataNode.h" #include #include #include #include #include #include -/// -/// \class QmitkNodeQmitkNodeDescriptor -/// \brief QmitkNodeQmitkNodeDescriptor is Decorator class for the mitk::DataNode -/// which enhances certain mitk::DataNode by additional infos needed by the GUI (Icon, ...) -/// -/// Moreover, QmitkNodeQmitkNodeDescriptor stores a Menu for actions that can be taken -/// for a certain DataNode, e.g. for DataNodes containing images this menu -/// can be filled with Image Filter Actions, etc. -/// -/// \sa QmitkDataNodeQmitkNodeDescriptorManager -/// +/** + * \ingroup QmitkModule + * \brief QmitkNodeQmitkNodeDescriptor is Decorator class for + * the mitk::DataNode which enhances certain mitk::DataNode by additional + * infos needed by the GUI (Icon, ...) + * + * Moreover, QmitkNodeQmitkNodeDescriptor stores a Menu for actions that can be taken + * for a certain DataNode, e.g. for DataNodes containing images this menu + * can be filled with Image Filter Actions, etc. + * + * \sa QmitkDataNodeQmitkNodeDescriptorManager + */ class QMITK_EXPORT QmitkNodeDescriptor : public QObject { Q_OBJECT public: /// /// Creates a new QmitkNodeQmitkNodeDescriptor /// QmitkNodeDescriptor(const QString& _ClassName, const QString& _PathToIcon , mitk::NodePredicateBase* _Predicate, QObject* parent); /// /// Deletes all actions /// virtual ~QmitkNodeDescriptor(); /// /// Returns a name for this class of DataNodes (e.g. "Image", "Image Mask", etc.) /// virtual QString GetClassName() const; /// /// Returns an Icon for this class of DataNodes /// virtual QIcon GetIcon() const; /// /// Returns an Icon for this class of DataNodes /// virtual QAction* GetSeparator() const; /// /// Check if this class describes the given node /// virtual bool CheckNode(const mitk::DataNode* node) const; /// /// Create and return an action with this descriptor as owner /// virtual void AddAction ( QAction * action, bool isBatchAction=true ); /// /// Remove and delete (!) an action /// virtual void RemoveAction(QAction* _Action); /// /// Get all actions associated with this class of nodes /// virtual QList GetActions() const; /// /// Get all actions for this descriptor class that can be executed on multiple nodes /// (no priot knowledge abpout the node is required) /// virtual QList GetBatchActions() const; public slots: /// Called when an action was destroyed void ActionDestroyed ( QObject * obj = 0 ); protected: QString m_ClassName; QString m_PathToIcon; mitk::NodePredicateBase::Pointer m_Predicate; QList m_Actions; QList m_BatchActions; QAction* m_Separator; }; #endif // QmitkNodeDescriptor_h diff --git a/Modules/Qmitk/QmitkNodeDescriptorManager.h b/Modules/Qmitk/QmitkNodeDescriptorManager.h index 7b7784fb57..af4a1ba8fb 100644 --- a/Modules/Qmitk/QmitkNodeDescriptorManager.h +++ b/Modules/Qmitk/QmitkNodeDescriptorManager.h @@ -1,116 +1,116 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkNodeDescriptorManager_h #define QmitkNodeDescriptorManager_h #include #include "QmitkNodeDescriptor.h" -/// -/// \class QmitkNodeDescriptorManager -/// \brief QmitkNodeDescriptorManager manages a set of QmitkNodeDescriptors -/// -/// \sa QmitkNodeDescriptor -/// +/** + * \ingroup QmitkModule + * \brief QmitkNodeDescriptorManager manages a set of QmitkNodeDescriptors + * + * \sa QmitkNodeDescriptor + */ class QMITK_EXPORT QmitkNodeDescriptorManager : public QObject { Q_OBJECT public: /// /// \return the solely instance of QmitkNodeDescriptorManager /// static QmitkNodeDescriptorManager* GetInstance(); /// /// Initializes the QmitkNodeDescriptorManager. /// Adds a few standard Descriptors. /// This Descriptors are added: /// - A QmitkNodeDescriptor for the class of "Image" DataNodes /// - A QmitkNodeDescriptor for the class of "Image Mask" DataNodes /// - A QmitkNodeDescriptor for the class of "Surface" DataNodes /// - A QmitkNodeDescriptor for the class of "PointSet" DataNodes /// virtual void Initialize(); /// /// Adds a new descriptor to the manager. The manager takes the ownership. /// void AddDescriptor(QmitkNodeDescriptor* _Descriptor); /// /// Removes and deletes a descriptor from the manager /// void RemoveDescriptor(QmitkNodeDescriptor* _Descriptor); /// /// Get the last descriptor in the descriptors list that matches the given node. /// *Attention*: More specialized Descriptors should therefore be appended at /// the end of the list, e.g. first add "Image", then add "Image Mask" /// /// \return a QmitkNodeDescriptor for the given node or a QmitkNodeDescriptor describing unknown nodes (never 0) /// \sa AddDescriptor() /// QmitkNodeDescriptor* GetDescriptor(const mitk::DataNode* _Node) const; /// /// Get the last QmitkNodeDescriptor for the given class name /// /// \return a QmitkNodeDescriptor for the given class name or 0 if there is no QmitkNodeDescriptor for _ClassName /// QmitkNodeDescriptor* GetDescriptor(const QString& _ClassName) const; /// /// \return The UnknownDataNodeDescriptor, which is the default Descriptor for all Nodes. /// QmitkNodeDescriptor* GetUnknownDataNodeDescriptor() const; /// /// Returns a list of all actions that are associated with the given node. /// If there are more than one Descriptors for this node all actions /// will be merged together. /// E.g. all actions from the "unknown" DataNodes will be added to /// this list. Generic Actions like Save, Load, etc. are stored there. /// QList GetActions(const mitk::DataNode* _Node) const; /// /// \return a list of actions associated with the given nodes /// QList GetActions( const QList& _Nodes ) const; /// /// Deletes all Descriptors in the list /// virtual ~QmitkNodeDescriptorManager(); protected: /// /// Creates the m_UnknownDataNodeDescriptor /// Calls Initialize /// QmitkNodeDescriptorManager(); protected: /// /// This is the standard QmitkNodeDescriptor matching every node /// QmitkNodeDescriptor* m_UnknownDataNodeDescriptor; /// /// Holds all user defined descriptors /// QList m_NodeDescriptors; }; #endif // QmitkNodeDescriptorManager_h diff --git a/Modules/Qmitk/QmitkProgressBar.h b/Modules/Qmitk/QmitkProgressBar.h index 1771572883..dbbf1fed9b 100644 --- a/Modules/Qmitk/QmitkProgressBar.h +++ b/Modules/Qmitk/QmitkProgressBar.h @@ -1,85 +1,86 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKPROGRESSBAR_H #define QMITKPROGRESSBAR_H #include #include #include -//##Documentation -//## @brief QT-Toolkit/GUI dependent class that provides the QT's ProgressBar -//## -//## All mitk-classes will call this class for output: -//## mitk::ProgressBar::GetInstance(); - +/** + * \ingroup QmitkModule + * \brief QT-Toolkit/GUI dependent class that provides the QT's ProgressBar + * + * All mitk-classes will call this class for output: + * mitk::ProgressBar::GetInstance(); + */ class QMITK_EXPORT QmitkProgressBar : public QProgressBar, public mitk::ProgressBarImplementation { Q_OBJECT public: //##Documentation //##@brief Constructor; //## holds param instance internally and connects this to the mitkProgressBar QmitkProgressBar(QWidget * parent = 0, const char * name = 0); //##Documentation //##@brief Destructor virtual ~QmitkProgressBar(); //##Documentation //## @brief Sets whether the current progress value is displayed. virtual void SetPercentageVisible(bool visible); //##Documentation //## @brief Adds steps to totalSteps. virtual void AddStepsToDo(unsigned int steps); //##Documentation //## @brief Sets the current amount of progress to current progress + steps. //## @param: steps the number of steps done since last Progress(int steps) call. virtual void Progress(unsigned int steps); signals: void SignalAddStepsToDo(unsigned int steps); void SignalProgress(unsigned int steps); void SignalSetPercentageVisible(bool visible); protected slots: virtual void SlotAddStepsToDo(unsigned int steps); virtual void SlotProgress(unsigned int steps); virtual void SlotSetPercentageVisible(bool visible); private: //##Documentation //## @brief Reset the progress bar. The progress bar "rewinds" and shows no progress. void Reset(); unsigned int m_TotalSteps; unsigned int m_Progress; }; #endif /* define QMITKPROGRESSBAR_H */ diff --git a/Modules/Qmitk/QmitkPropertiesTableEditor.h b/Modules/Qmitk/QmitkPropertiesTableEditor.h index a449024f4c..cc58d6539f 100644 --- a/Modules/Qmitk/QmitkPropertiesTableEditor.h +++ b/Modules/Qmitk/QmitkPropertiesTableEditor.h @@ -1,90 +1,91 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkPropertiesTableEditor_h #define QmitkPropertiesTableEditor_h #include /// Own includes. #include "mitkDataNode.h" /// Toolkit includes. #include /// Forward declarations. class QmitkPropertiesTableModel; class QTableView; class QLineEdit; -/// -/// \class QmitkPropertiesTableEditor -/// \brief Combines a QTableView along with a QmitkPropertiesTableModel to a reusable -/// Property Editor component. -/// -/// \see QmitkPropertyDelegate +/** + * \ingroup QmitkModule + * \brief Combines a QTableView along with a QmitkPropertiesTableModel to a reusable + * Property Editor component. + * + * \see QmitkPropertyDelegate + */ class QMITK_EXPORT QmitkPropertiesTableEditor : public QWidget { Q_OBJECT public: /// /// Constructs a new QmitkDataStorageTableModel /// and sets the DataNode for this TableModel. QmitkPropertiesTableEditor(QWidget* parent = 0, Qt::WindowFlags f = 0,mitk::DataNode::Pointer _Node = 0); /// /// Standard dtor. Nothing to do here. virtual ~QmitkPropertiesTableEditor(); /// /// Convenience method. Sets the property list in the model. /// void SetPropertyList(mitk::PropertyList::Pointer _List); /// /// Get the model. /// QmitkPropertiesTableModel* getModel() const; QTableView* getTable() const; protected slots: void PropertyFilterKeyWordTextChanged(const QString & text); protected: /// /// Initialise empty GUI. /// virtual void init(); /// /// The table view that renders the property list. /// QTableView* m_NodePropertiesTableView; /// /// A text field in which the user can enter a filter keyword for the properties. Only properties containing with this keyword /// will be selected. /// QLineEdit* m_TxtPropertyFilterKeyWord; /// /// The property list table model. /// QmitkPropertiesTableModel* m_Model; }; #endif /* QMITKPROPERTIESTABLEMODEL_H_ */ diff --git a/Modules/Qmitk/QmitkPropertiesTableModel.h b/Modules/Qmitk/QmitkPropertiesTableModel.h index 31fd07ab3e..cb32daef5f 100644 --- a/Modules/Qmitk/QmitkPropertiesTableModel.h +++ b/Modules/Qmitk/QmitkPropertiesTableModel.h @@ -1,252 +1,252 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ /// Header guard. #ifndef QmitkPropertiesTableModel_h #define QmitkPropertiesTableModel_h #include //# Own includes #include "mitkDataNode.h" #include "mitkWeakPointer.h" //# Toolkit includes #include #include #include //# Forward declarations -/// -/// \class QmitkPropertiesTableModel -/// \brief A table model for showing and editing mitk::Properties. -/// -/// \see QmitkPropertyDelegate -/// +/** + * \ingroup QmitkModule + * \brief A table model for showing and editing mitk::Properties. + * + * \see QmitkPropertyDelegate + */ class QMITK_EXPORT QmitkPropertiesTableModel : public QAbstractTableModel { //# PUBLIC CTORS,DTOR,TYPEDEFS,CONSTANTS public: static const int PROPERTY_NAME_COLUMN = 0; static const int PROPERTY_VALUE_COLUMN = 1; /// /// Typedef for the complete Property Datastructure, which may be written as follows: /// Name->(mitk::BaseProperty::Pointer) /// typedef std::pair PropertyDataSet; /// /// Constructs a new QmitkDataStorageTableModel /// and sets the DataNode for this TableModel. QmitkPropertiesTableModel(QObject* parent = 0, mitk::PropertyList::Pointer _PropertyList=0); /// /// Standard dtor. Nothing to do here. virtual ~QmitkPropertiesTableModel(); //# PUBLIC GETTER public: /// /// Returns the property list of this table model. /// mitk::PropertyList::Pointer GetPropertyList() const; /// /// Overwritten from QAbstractTableModel. Returns the flags what can be done with the items (view, edit, ...) Qt::ItemFlags flags(const QModelIndex& index) const; /// /// Overwritten from QAbstractTableModel. Returns the flags what can be done with the items (view, edit, ...) QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; /// /// Overwritten from QAbstractTableModel. Returns the flags what can be done with the items (view, edit, ...) QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; /// /// Overwritten from QAbstractTableModel. Returns the flags what can be done with the items (view, edit, ...) int rowCount(const QModelIndex& parent = QModelIndex()) const; /// /// Overwritten from QAbstractTableModel. Returns the number of columns. That is usually two in this model: /// the properties name and its value. int columnCount(const QModelIndex &parent) const; //# PUBLIC SETTER public: /// /// Sets the Property List to show. Resets the whole model. If _PropertyList is NULL the model is empty. /// void SetPropertyList(mitk::PropertyList* _PropertyList); /// /// \brief Gets called when the list is about to be deleted. /// virtual void PropertyListDelete(const itk::Object *_PropertyList); /// /// \brief Called when a single property was changed. Send a model changed event to the Qt-outer world. /// virtual void PropertyModified(const itk::Object *caller, const itk::EventObject &event); /// /// \brief Called when a single property was changed. Send a model changed event to the Qt-outer world. /// virtual void PropertyDelete(const itk::Object *caller, const itk::EventObject &event); /// /// \brief Set a keyword for filtering of properties. Only properties beginning with this string will be shown /// virtual void SetFilterPropertiesKeyWord(std::string _FilterKeyWord); /// /// Overridden from QAbstractTableModel. Sets data at index for given role. /// bool setData(const QModelIndex &index, const QVariant &value, int role); /// /// \brief Reimplemented sort function from QAbstractTableModel to enable sorting on the table. /// void sort ( int column, Qt::SortOrder order = Qt::AscendingOrder ); //#PROTECTED INNER CLASSES protected: /// /// \struct PropertyDataSetCompareFunction /// \brief A struct that inherits from std::binary_function. You can use it in std::sort algorithm for sorting the property list elements. /// struct PropertyDataSetCompareFunction : public std::binary_function { /// /// \brief Specifies field of the property with which it will be sorted. /// enum CompareCriteria { CompareByName = 0, CompareByValue }; /// /// \brief Specifies Ascending/descending ordering. /// enum CompareOperator { Less = 0, Greater }; /// /// \brief Creates a PropertyDataSetCompareFunction. A CompareCriteria and a CompareOperator must be given. /// PropertyDataSetCompareFunction(CompareCriteria _CompareCriteria = CompareByName, CompareOperator _CompareOperator = Less); /// /// \brief The reimplemented compare function. /// bool operator()(const PropertyDataSet& _Left , const PropertyDataSet& _Right) const; protected: CompareCriteria m_CompareCriteria; CompareOperator m_CompareOperator; }; /// /// An unary function for selecting Properties in a vector by a key word. /// struct PropertyListElementFilterFunction : public std::unary_function { PropertyListElementFilterFunction(const std::string& m_FilterKeyWord); /// /// \brief The reimplemented compare function. /// bool operator()(const PropertyDataSet& _Elem) const; protected: std::string m_FilterKeyWord; }; //# PROTECTED GETTER protected: /// /// \brief Searches for the specified property and returns the row of the element in this QTableModel. /// If any errors occur, the function returns -1. /// int FindProperty(const mitk::BaseProperty* _Property) const; //# PROTECTED SETTER protected: /// /// Adds a property dataset to the current selection. /// When a property is added a modified and delete listener /// is appended. /// void AddSelectedProperty(PropertyDataSet& _PropertyDataSet); /// /// Removes a property dataset from the current selection. /// When a property is removed the modified and delete listener /// are also removed. /// void RemoveSelectedProperty(unsigned int _Index); /// /// Reset is called when a new filter keyword is set or a new /// PropertyList is set. First of all, all priorly selected /// properties are removed. Then all properties to be /// selected (specified by the keyword) are added to the selection. /// void Reset(); //# PROTECTED MEMBERS protected: /// /// Holds the pointer to the properties list. Dont use smart pointers here. Instead: Listen /// to the delete event. mitk::WeakPointer m_PropertyList; /// /// Store the properties in a vector so that they may be sorted std::vector m_SelectedProperties; /// /// \brief Holds all tags of Modified Event Listeners. We need it to remove them again. /// std::vector m_PropertyModifiedObserverTags; /// /// \brief Holds all tags of Modified Event Listeners. We need it to remove them again. /// std::vector m_PropertyDeleteObserverTags; /// /// \brief Indicates if this class should neglect all incoming events because /// the class itself triggered the event (e.g. when a property was edited). /// bool m_BlockEvents; /// /// \brief The property is true when the property list is sorted in descending order. /// bool m_SortDescending; /// /// \brief If set to any value, only properties containing the specified keyword in their name will be shown. /// std::string m_FilterKeyWord; }; #endif /* QMITKPROPERTIESTABLEMODEL_H_ */ diff --git a/Modules/Qmitk/QmitkPropertyDelegate.h b/Modules/Qmitk/QmitkPropertyDelegate.h index 8b040edd22..b1faf40a2b 100644 --- a/Modules/Qmitk/QmitkPropertyDelegate.h +++ b/Modules/Qmitk/QmitkPropertyDelegate.h @@ -1,88 +1,89 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkPropertyDelegate_h #define QmitkPropertyDelegate_h #include /// Own includes. #include "mitkBaseProperty.h" /// Toolkit includes. #include /// Forward declarations. -/// -/// \class QmitkPropertyDelegate -/// \brief An item delegate for rendering and editing mitk::Properties in a QTableView. -/// -/// \see QmitkPropertiesTableModel +/** + * \ingroup QmitkModule + * \brief An item delegate for rendering and editing mitk::Properties in a QTableView. + * + * \see QmitkPropertiesTableModel + */ class QMITK_EXPORT QmitkPropertyDelegate : public QStyledItemDelegate { Q_OBJECT public: /// /// Creates a new PropertyDelegate. /// QmitkPropertyDelegate(QObject *parent = 0); /// /// Renders a specific property (overwritten from QItemDelegate) /// void paint(QPainter *painter, const QStyleOptionViewItem &option , const QModelIndex &index) const; /// /// Create an editor for a specific property (overwritten from QItemDelegate) /// QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option , const QModelIndex &index) const; /// /// Create an editor for a specific property (overwritten from QItemDelegate) /// void setEditorData(QWidget *editor, const QModelIndex &index) const; /// /// When the user accepts input this func commits the data to the model (overwritten from QItemDelegate) /// void setModelData(QWidget *editor, QAbstractItemModel* model , const QModelIndex &index) const; /// /// \brief Fit an editor to some geometry (overwritten from QItemDelegate) /// void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; protected: bool eventFilter( QObject *o, QEvent *e ); private slots: /// /// Invoked when the user accepts editor input, that is when he does not pushes ESC. /// void commitAndCloseEditor(); void showColorDialog(); void ComboBoxCurrentIndexChanged ( int index ) ; void SpinBoxValueChanged ( const QString& value ) ; }; #endif /* QMITKPROPERTIESTABLEMODEL_H_ */ diff --git a/Modules/Qmitk/QmitkRegisterClasses.h b/Modules/Qmitk/QmitkRegisterClasses.h index 36292c926d..f172313e99 100644 --- a/Modules/Qmitk/QmitkRegisterClasses.h +++ b/Modules/Qmitk/QmitkRegisterClasses.h @@ -1,25 +1,26 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkRegisterClassesHIncluded #define QmitkRegisterClassesHIncluded #include +/// \ingroup QmitkModule QMITK_EXPORT void QmitkRegisterClasses(); #endif diff --git a/Modules/Qmitk/QmitkRenderWindow.h b/Modules/Qmitk/QmitkRenderWindow.h index 398f0df3c2..0763cd2e1e 100644 --- a/Modules/Qmitk/QmitkRenderWindow.h +++ b/Modules/Qmitk/QmitkRenderWindow.h @@ -1,181 +1,180 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66 #define QMITKRENDERWINDOW_H_HEADER_INCLUDED_C1C40D66 #include "mitkRenderWindowBase.h" #include #include "QVTKWidget.h" #include "QmitkRenderWindowMenu.h" #include "mitkInteractionEventConst.h" -#include class QmitkStdMultiWidget; class QDragEnterEvent; class QDropEvent; /** + * \ingroup QmitkModule * \brief MITK implementation of the QVTKWidget - * \ingroup Renderer */ class QMITK_EXPORT QmitkRenderWindow: public QVTKWidget, public mitk::RenderWindowBase { Q_OBJECT public: QmitkRenderWindow(QWidget *parent = 0, QString name = "unnamed renderwindow", mitk::VtkPropRenderer* renderer = NULL, mitk::RenderingManager* renderingManager = NULL); virtual ~QmitkRenderWindow(); /** * \brief Whether Qt events should be passed to parent (default: true) * * With introduction of the QVTKWidget the behaviour regarding Qt events changed. * QVTKWidget "accepts" Qt events like mouse clicks (i.e. set an "accepted" flag). * When this flag is set, Qt fininshed handling of this event -- otherwise it is * reached through to the widget's parent. * * This reaching through to the parent was implicitly required by QmitkMaterialWidget / QmitkMaterialShowCase. *QmitkStdMultiWidget * The default behaviour of QmitkRenderWindow is now to clear the "accepted" flag * of Qt events after they were handled by QVTKWidget. This way parents can also * handle events. * * If you don't want this behaviour, call SetResendQtEvents(true) on your render window. */ virtual void SetResendQtEvents(bool resend); // Set Layout Index to define the Layout Type void SetLayoutIndex(unsigned int layoutIndex); // Get Layout Index to define the Layout Type unsigned int GetLayoutIndex(); //MenuWidget need to update the Layout Design List when Layout had changed void LayoutDesignListChanged(int layoutDesignIndex); void HideRenderWindowMenu(); //Activate or Deactivate MenuWidget. void ActivateMenuWidget(bool state, QmitkStdMultiWidget* stdMultiWidget = 0); bool GetActivateMenuWidgetFlag() { return m_MenuWidgetActivated; } // Get it from the QVTKWidget parent virtual vtkRenderWindow* GetVtkRenderWindow() { return GetRenderWindow(); } virtual vtkRenderWindowInteractor* GetVtkRenderWindowInteractor() { return NULL; } void FullScreenMode(bool state); protected: // overloaded move handler virtual void moveEvent(QMoveEvent* event); // overloaded show handler void showEvent(QShowEvent* event); // overloaded resize handler virtual void resizeEvent(QResizeEvent* event); // overloaded paint handler virtual void paintEvent(QPaintEvent* event); // overloaded mouse press handler virtual void mousePressEvent(QMouseEvent* event); // overloaded mouse move handler virtual void mouseMoveEvent(QMouseEvent* event); // overloaded mouse release handler virtual void mouseReleaseEvent(QMouseEvent* event); // overloaded key press handler virtual void keyPressEvent(QKeyEvent* event); // overloaded enter handler virtual void enterEvent(QEvent*); // overloaded leave handler virtual void leaveEvent(QEvent*); /// \brief Simply says we accept the event type. virtual void dragEnterEvent(QDragEnterEvent *event); /// \brief If the dropped type is application/x-mitk-datanodes we process the request by converting to mitk::DataNode pointers and emitting the NodesDropped signal. virtual void dropEvent(QDropEvent * event); #ifndef QT_NO_WHEELEVENT // overload wheel mouse event virtual void wheelEvent(QWheelEvent*); #endif void AdjustRenderWindowMenuVisibility(const QPoint& pos); signals: void ResetView(); // \brief int parameters are enum from QmitkStdMultiWidget void ChangeCrosshairRotationMode(int); void SignalLayoutDesignChanged(int layoutDesignIndex); void moved(); void resized(); /// \brief Emits a signal to say that this window has had the following nodes dropped on it. void NodesDropped(QmitkRenderWindow *thisWindow, std::vector nodes); protected slots: void OnChangeLayoutDesign(int layoutDesignIndex); void OnWidgetPlaneModeChanged(int); void DeferredHideMenu(); private: // Helper Functions to Convert Qt-Events to Mitk-Events mitk::Point2D GetMousePosition(QMouseEvent* me); mitk::Point2D GetMousePosition(QWheelEvent* we); mitk::MouseButtons GetEventButton(QMouseEvent* me); mitk::MouseButtons GetButtonState(QMouseEvent* me); mitk::ModifierKeys GetModifiers(QMouseEvent* me); mitk::MouseButtons GetButtonState(QWheelEvent* we); mitk::ModifierKeys GetModifiers(QWheelEvent* we); mitk::ModifierKeys GetModifiers(QKeyEvent* ke); std::string GetKeyLetter(QKeyEvent* ke); int GetDelta(QWheelEvent* we); bool m_ResendQtEvents; QmitkRenderWindowMenu* m_MenuWidget; bool m_MenuWidgetActivated; unsigned int m_LayoutIndex; }; #endif diff --git a/Modules/Qmitk/QmitkRenderWindowMenu.h b/Modules/Qmitk/QmitkRenderWindowMenu.h index 0c4646b7c1..9661a30ea8 100644 --- a/Modules/Qmitk/QmitkRenderWindowMenu.h +++ b/Modules/Qmitk/QmitkRenderWindowMenu.h @@ -1,339 +1,342 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkRenderWindowMenu_h #define QmitkRenderWindowMenu_h #if defined(_WIN32) || defined(__APPLE__) #define QMITK_USE_EXTERNAL_RENDERWINDOW_MENU #endif #include #include "mitkBaseRenderer.h" #include #include #include #include #include #include #include class QmitkStdMultiWidget; /** -* \brief The QmitkRenderWindowMenu is a popup Widget which shows up when the mouse curser enter a QmitkRenderWindow. -* The Menu Widget is located in the right top corner of each RenderWindow. It includes different settings. For example -* the layout design can be changed with the setting button. Switching between full-screen mode and layout design can be done -* with the full-screen button. Splitting the Widget horizontal or vertical as well closing the Widget is not implemented yet. -* The popup Widget can be deactivated with ActivateMenuWidget(false) in QmitkRenderWindow. -* -* \ingroup Renderer -* -* \sa QmitkRenderWindow -* \sa QmitkStdMultiWidget -* -*/ - + * \ingroup QmitkModule + * \brief The QmitkRenderWindowMenu is a popup Widget which shows + * up when the mouse curser enter a QmitkRenderWindow. + * The Menu Widget is located in the right top corner of each + * RenderWindow. It includes different settings. For example + * the layout design can be changed with the setting button. Switching + * between full-screen mode and layout design can be done + * with the full-screen button. Splitting the Widget horizontal or + * vertical as well closing the Widget is not implemented yet. + * The popup Widget can be deactivated with ActivateMenuWidget(false) in + * QmitkRenderWindow. + * + * \sa QmitkRenderWindow + * \sa QmitkStdMultiWidget + * + */ class QMITK_EXPORT QmitkRenderWindowMenu : public QWidget { Q_OBJECT public: QmitkRenderWindowMenu( QWidget* parent = 0, Qt::WFlags f = 0, mitk::BaseRenderer * b = 0, QmitkStdMultiWidget* mw = 0 ); virtual ~QmitkRenderWindowMenu(); /*! Return visibility of settings menu. The menu is connected with m_SettingsButton and includes layout direction (axial, coronal .. ) and layout design (standard layout, 2D images top, 3D bottom ... ). */ bool GetSettingsMenuVisibilty() { if( m_Settings == NULL) return false; else return m_Settings->isVisible(); } /*! Set layout index. Defines layout direction (axial, coronal, sagital or threeD) of the parent. */ void SetLayoutIndex( unsigned int layoutIndex ); /*! Return layout direction of parent (axial, coronal, sagital or threeD) */ unsigned int GetLayoutIndex() { return m_Layout; } /*! Update list of layout design (standard layout, 2D images top, 3D bottom ..). Set action of current layout design to disable and all other to enable. */ void UpdateLayoutDesignList( int layoutDesignIndex ); /*! Move menu widget to correct position (right upper corner). E.g. it is necessary when the full-screen mode is activated.*/ #ifdef QMITK_USE_EXTERNAL_RENDERWINDOW_MENU void MoveWidgetToCorrectPos(float opacity); #else void MoveWidgetToCorrectPos(float /*opacity*/); #endif void ChangeFullScreenMode( bool state ); void NotifyNewWidgetPlanesMode( int mode ); protected: /*! Create menu widget. The menu contains five QPushButtons (hori-split, verti-split, full-screen, settings and close button) and their signal/slot connection for handling. */ void CreateMenuWidget(); /*! Create settings menu which contains layout direction and the different layout designs. */ void CreateSettingsWidget(); /*! Reimplemented from QWidget. The paint event is a request to repaint all or part of a widget.*/ void paintEvent(QPaintEvent *event); /*! Update list of layout direction (axial, coronal, sagital or threeD). Set action of currect layout direction to disable and all other to enable. Normaly the user can switch here between the different layout direction, but this is not supported yet. */ void UpdateLayoutList(); /*! Change Icon of full-screen button depending on full-screen mode. */ void ChangeFullScreenIcon(); int currentCrosshairRotationMode; public slots: void SetCrossHairVisibility( bool state ) ; signals: void ResetView(); // == "global reinit" // \brief int parameters are enum from QmitkStdMultiWidget void ChangeCrosshairRotationMode(int); /*! emit signal, when layout design changed by the setting menu.*/ void SignalChangeLayoutDesign( int layoutDesign ); public slots: void DeferredHideMenu( ); void DeferredShowMenu( ); void smoothHide( ); protected slots: /// /// this function is continously called by a timer /// to do the auto rotation /// void AutoRotateNextStep(); /// /// this function is invoked when the auto-rotate action /// is clicked /// void OnAutoRotationActionTriggered(); void enterEvent( QEvent* /*e*/ ); void leaveEvent( QEvent* /*e*/ ); void OnTSNumChanged(int); void OnCrosshairRotationModeSelected(QAction*); /*! slot for activating/deactivating the full-screen mode. The slot is connected to the clicked() event of m_FullScreenButton. Activating the full-screen maximize the current widget, deactivating restore If layout design changed by the settings menu, the full-Screen mode is automatically switch to false. */ void OnFullScreenButton( bool checked ); /*! Slot for opening setting menu. The slot is connected to the clicked() event of m_SettingsButton. The settings menu includes differen layout directions (axial, coronal, saggital and 3D) as well all layout design (standard layout, 2D images top, 3D bottom ..)*/ void OnSettingsButton( bool checked ); /*! Slot for changing layout design to standard layout. The slot is connected to the triggered() signal of m_DefaultLayoutAction. */ void OnChangeLayoutToDefault(bool); /*! Slot for changing layout design to 2D images top, 3D bottom layout. The slot is connected to the triggered() signal of m_2DImagesUpLayoutAction. */ void OnChangeLayoutTo2DImagesUp(bool); /*! Slot for changing layout design to 2D images left, 3D right layout. The slot is connected to the triggered() signal of m_2DImagesLeftLayoutAction. */ void OnChangeLayoutTo2DImagesLeft(bool); /*! Slot for changing layout to Big 3D layout. The slot is connected to the triggered() signal of m_Big3DLayoutAction. */ void OnChangeLayoutToBig3D(bool); /*! Slot for changing layout design to Axial plane layout. The slot is connected to the triggered() signal of m_Widget1LayoutAction. */ void OnChangeLayoutToWidget1(bool); /*! Slot for changing layout design to Sagittal plane layout. The slot is connected to the triggered() signal of m_Widget2LayoutAction. */ void OnChangeLayoutToWidget2(bool); /*! Slot for changing layout design to Coronal plane layout. The slot is connected to the triggered() signal of m_Widget3LayoutAction. */ void OnChangeLayoutToWidget3(bool); /*! Slot for changing layout design to Coronal top, 3D bottom layout. The slot is connected to the triggered() signal of m_RowWidget3And4LayoutAction. */ void OnChangeLayoutToRowWidget3And4(bool); /*! Slot for changing layout design to Coronal left, 3D right layout. The slot is connected to the triggered() signal of m_ColumnWidget3And4LayoutAction. */ void OnChangeLayoutToColumnWidget3And4(bool); /*! Slot for changing layout design to Sagittal top, Coronal n 3D bottom layout. The slot is connected to the triggered() signal of m_SmallUpperWidget2Big3and4LayoutAction. */ void OnChangeLayoutToSmallUpperWidget2Big3and4(bool); /*! Slot for changing layout design to Axial n Sagittal left, 3D right layout. The slot is connected to the triggered() signal of m_2x2Dand3DWidgetLayoutAction. */ void OnChangeLayoutTo2x2Dand3DWidget(bool); /*! Slot for changing layout design to Axial n 3D left, Sagittal right layout. The slot is connected to the triggered() signal of m_Left2Dand3DRight2DLayoutAction. */ void OnChangeLayoutToLeft2Dand3DRight2D(bool); void OnCrossHairMenuAboutToShow(); public: /*! enum for layout direction*/ enum { #ifdef _MSC_VER TRANSVERSAL, // deprecated #endif AXIAL = 0, SAGITTAL, CORONAL, THREE_D }; #ifdef __GNUC__ __attribute__ ((deprecated)) static const int TRANSVERSAL = AXIAL; #endif /*! enum for layout design */ enum { LAYOUT_DEFAULT, LAYOUT_2DIMAGEUP, LAYOUT_2DIMAGELEFT, LAYOUT_BIG3D, #ifdef _MSC_VER LAYOUT_TRANSVERSAL, // deprecated #endif LAYOUT_AXIAL = LAYOUT_BIG3D + 1, LAYOUT_SAGITTAL, LAYOUT_CORONAL, LAYOUT_2X2DAND3DWIDGET, LAYOUT_ROWWIDGET3AND4, LAYOUT_COLUMNWIDGET3AND4, LAYOUT_ROWWIDGETSMALL3ANDBIG4, //not in use in this class, but we need it here to synchronize with the SdtMultiWidget. LAYOUT_SMALLUPPERWIDGET2BIGAND4, LAYOUT_LEFT2DAND3DRIGHT2D }; #ifdef __GNUC__ __attribute__ ((deprecated)) static const int LAYOUT_TRANSVERSAL = LAYOUT_AXIAL; #endif void ShowMenu(); void HideMenu(); protected: QPushButton* m_CrosshairModeButton; //QAction* m_ShowHideCrosshairVisibilityAction; /*! QPushButton for activating/deactivating full-screen mode*/ QPushButton* m_FullScreenButton; /*! QPushButton for open the settings menu*/ QPushButton* m_SettingsButton; /*! QAction for Default layout design */ QAction* m_DefaultLayoutAction; /*! QAction for 2D images up layout design */ QAction* m_2DImagesUpLayoutAction; /*! QAction for 2D images left layout design */ QAction* m_2DImagesLeftLayoutAction; /*! QAction for big 3D layout design */ QAction* m_Big3DLayoutAction; /*! QAction for big axial layout design */ QAction* m_Widget1LayoutAction; /*! QAction for big saggital layout design */ QAction* m_Widget2LayoutAction; /*! QAction for big coronal layout design */ QAction* m_Widget3LayoutAction; /*! QAction for coronal top, 3D bottom layout design */ QAction* m_RowWidget3And4LayoutAction; /*! QAction for coronal left, 3D right layout design */ QAction* m_ColumnWidget3And4LayoutAction; /*! QAction for sagittal top, coronal n 3D bottom layout design */ QAction* m_SmallUpperWidget2Big3and4LayoutAction; /*! QAction for axial n sagittal left, 3D right layout design */ QAction* m_2x2Dand3DWidgetLayoutAction; /*! QAction for axial n 3D left, sagittal right layout design*/ QAction* m_Left2Dand3DRight2DLayoutAction; QLabel *m_TSLabel; /*! QMenu containg all layout direction and layout design settings.*/ QMenu* m_Settings; QMenu* m_CrosshairMenu; /*! Index of layout direction. 0: axial; 1: saggital; 2: coronal; 3: threeD */ unsigned int m_Layout; /*! Index of layout design. 0: LAYOUT_DEFAULT; 1: LAYOUT_2DIMAGEUP; 2: LAYOUT_2DIMAGELEFT; 3: LAYOUT_BIG3D 4: LAYOUT_AXIAL; 5: LAYOUT_SAGITTAL; 6: LAYOUT_CORONAL; 7: LAYOUT_2X2DAND3DWIDGET; 8: LAYOUT_ROWWIDGET3AND4; 9: LAYOUT_COLUMNWIDGET3AND4; 10: LAYOUT_ROWWIDGETSMALL3ANDBIG4; 11: LAYOUT_SMALLUPPERWIDGET2BIGAND4; 12: LAYOUT_LEFT2DAND3DRIGHT2D */ unsigned int m_LayoutDesign; /*! Store index of old layout design. It is used e.g. for the full-screen mode, when deactivating the mode the former layout design will restore.*/ unsigned int m_OldLayoutDesign; /*! Flag if full-screen mode is activated or deactivated. */ bool m_FullScreenMode; bool m_Entered; bool m_Hidden; private: mitk::BaseRenderer::Pointer m_Renderer; QmitkStdMultiWidget* m_MultiWidget; /// /// a timer for the auto rotate action /// QTimer m_AutoRotationTimer; }; #endif // QmitkRenderWindowMenu_H diff --git a/Modules/Qmitk/QmitkRenderingManager.h b/Modules/Qmitk/QmitkRenderingManager.h index 610d1be80e..dd0b526c49 100644 --- a/Modules/Qmitk/QmitkRenderingManager.h +++ b/Modules/Qmitk/QmitkRenderingManager.h @@ -1,88 +1,88 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKRENDERINGMANAGER_H_HEADER_INCLUDED_C135A197 #define QMITKRENDERINGMANAGER_H_HEADER_INCLUDED_C135A197 #include #include "mitkRenderingManager.h" #include #include class QmitkRenderingManagerInternal; class QmitkRenderingManagerFactory; /** + * \ingroup QmitkModule * \brief Qt specific implementation of mitk::RenderingManager. * * This implementation defines a QmitkRenderingRequestEvent to realize the * rendering request process. The event must be handled by the Qmitk * interface to Qt (QmitkRenderWindow). * * Note: it may be necessary to remove all pending RenderingRequestEvents * from the system's event processing pipeline during system shutdown to * make sure that dangling events do not lead to unexpected behavior. * - * \ingroup Renderer */ class QMITK_EXPORT QmitkRenderingManager : public QObject, public mitk::RenderingManager { Q_OBJECT public: mitkClassMacro( QmitkRenderingManager, mitk::RenderingManager ); virtual ~QmitkRenderingManager(); virtual void DoMonitorRendering(); virtual void DoFinishAbortRendering(); virtual bool event( QEvent *event ); protected: itkFactorylessNewMacro(Self); QmitkRenderingManager(); virtual void GenerateRenderingRequestEvent(); virtual void StartOrResetTimer(); int pendingTimerCallbacks; protected slots: void TimerCallback(); private: friend class QmitkRenderingManagerFactory; }; class QmitkRenderingRequestEvent : public QEvent { public: enum Type { RenderingRequest = QEvent::MaxUser - 1024 }; QmitkRenderingRequestEvent() : QEvent( (QEvent::Type) RenderingRequest ) {}; }; #endif /* MITKRenderingManager_H_HEADER_INCLUDED_C135A197 */ diff --git a/Modules/Qmitk/QmitkRenderingManagerFactory.h b/Modules/Qmitk/QmitkRenderingManagerFactory.h index a9d7bd927a..635afdb5e1 100644 --- a/Modules/Qmitk/QmitkRenderingManagerFactory.h +++ b/Modules/Qmitk/QmitkRenderingManagerFactory.h @@ -1,51 +1,51 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKRENDERINGMANAGERFACTORY_H_HEADER_INCLUDED_C135A197 #define QMITKRENDERINGMANAGERFACTORY_H_HEADER_INCLUDED_C135A197 #include #include "mitkRenderingManagerFactory.h" /** + * \ingroup QmitkModule * \brief Qt specific implementation of mitk::RenderingManagerFactory. * * This class create QmitkRenderingManager instances via * #CreateRenderingManager. * * A static instance of QmitkRenderingManagerFactory is created in * QmitkRenderWindow, forcing the usage of QmitkRenderingManager for the Qt * platform. - * \ingroup Renderer */ class QMITK_EXPORT QmitkRenderingManagerFactory : public mitk::RenderingManagerFactory { public: QmitkRenderingManagerFactory(); ~QmitkRenderingManagerFactory(); virtual mitk::RenderingManager::Pointer CreateRenderingManager() const; private: }; #endif diff --git a/Modules/Qmitk/QmitkServiceListWidget.h b/Modules/Qmitk/QmitkServiceListWidget.h index 0c5e5d037b..aefac9a464 100644 --- a/Modules/Qmitk/QmitkServiceListWidget.h +++ b/Modules/Qmitk/QmitkServiceListWidget.h @@ -1,239 +1,245 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _QmitkServiceListWidget_H_INCLUDED #define _QmitkServiceListWidget_H_INCLUDED #include "QmitkExports.h" #include "ui_QmitkServiceListWidgetControls.h" #include //QT headers #include #include //Microservices #include "usServiceReference.h" #include "usModuleContext.h" #include "usServiceEvent.h" #include "usServiceInterface.h" /** -* @brief This widget provides abstraction for the handling of MicroServices . Place one in your Plugin and set it to look for a certain interface. -* One can also specify a filter and / or a property to use for captioning of the services. It also offers functionality to signal -* ServiceEvents and to return the actual classes, so only a minimum of interaction with the MicroserviceInterface is required. -* To get started, just put it in your Plugin or Widget, call the Initialize Method and optionally connect it's signals. -* As QT limits templating possibilities, events only throw ServiceReferences. You can manually dereference them using TranslateServiceReference() -* -* @ingroup QMITK + * \ingroup QmitkModule + * + * \brief This widget provides abstraction for the handling of MicroServices. + * + * Place one in your Plugin and set it to look for a certain interface. + * One can also specify a filter and / or a property to use for captioning of + * the services. It also offers functionality to signal + * ServiceEvents and to return the actual classes, so only a minimum of + * interaction with the MicroserviceInterface is required. + * To get started, just put it in your Plugin or Widget, call the Initialize + * Method and optionally connect it's signals. + * As QT limits templating possibilities, events only throw ServiceReferences. + * You can manually dereference them using TranslateServiceReference() */ class QMITK_EXPORT QmitkServiceListWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT private: mitk::ModuleContext* m_Context; /** \brief a filter to further narrow down the list of results*/ std::string m_Filter; /** \brief The name of the ServiceInterface that this class should list */ std::string m_Interface; /** \brief The name of the ServiceProperty that will be displayed in the list to represent the service */ std::string m_NamingProperty; public: static const std::string VIEW_ID; QmitkServiceListWidget(QWidget* p = 0, Qt::WindowFlags f1 = 0); virtual ~QmitkServiceListWidget(); /** \brief This method is part of the widget an needs not to be called separately. */ virtual void CreateQtPartControl(QWidget *parent); /** \brief This method is part of the widget an needs not to be called separately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); /** * \brief Will return true, if a service is currently selected and false otherwise. * * Call this before requesting service references to avoid invalid ServiceReferences. */ bool GetIsServiceSelected(); /** * \brief Returns the currently selected Service as a ServiceReference. * * If no Service is selected, the result will probably be a bad pointer. call GetIsServiceSelected() * beforehand to avoid this */ mitk::ServiceReference GetSelectedServiceReference(); /** * \brief Use this function to return the currently selected service as a class directly. * * Make sure you pass the appropriate type, or else this call will fail. * Usually, you will pass the class itself, not the SmartPointer, but the function returns a pointer. Example: * \verbatim mitk::USDevice::Pointer device = GetSelectedService(); \endverbatim */ template T* GetSelectedService() { mitk::ServiceReference ref = GetServiceForListItem( this->m_Controls->m_ServiceList->currentItem() ); return ( m_Context->GetService(ref) ); } /** * \brief Initializes the Widget with essential parameters. * * The string filter is an LDAP parsable String, compare mitk::ModuleContext for examples on filtering. * Pass class T to tell the widget which class it should filter for - only services of this class will be listed. * NamingProperty is a property that will be used to caption the Items in the list. If no filter is supplied, all * matching interfaces are shown. If no namingProperty is supplied, the interfaceName will be used to caption Items in the list. * For example, this Initialization will filter for all USDevices that are set to active. The USDevice's model will be used to display it in the list: * \verbatim std::string filter = "(&(" + mitk::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(IsActive=true))"; m_Controls.m_ActiveVideoDevices->Initialize(mitk::USImageMetadata::PROP_DEV_MODEL ,filter); * \endverbatim */ template void Initialize(const std::string& namingProperty = static_cast< std::string >(""),const std::string& filter = static_cast< std::string >("")) { std::string interfaceName ( us_service_interface_iid() ); m_Interface = interfaceName; InitPrivate(namingProperty, filter); } /** * \brief Translates a serviceReference to a class of the given type. * * Use this to translate the signal's parameters. To adhere to the MicroService contract, * only ServiceReferences stemming from the same widget should be used as parameters for this method. * \verbatim mitk::USDevice::Pointer device = TranslateReference(myDeviceReference); \endverbatim */ template T* TranslateReference(mitk::ServiceReference reference) { return dynamic_cast ( m_Context->GetService(reference) ); } /** *\brief This Function listens to ServiceRegistry changes and updates the list of services accordingly. * * The user of this widget does not need to call this method, it is instead used to recieve events from the module registry. */ void OnServiceEvent(const mitk::ServiceEvent event); signals: /** *\brief Emitted when a new Service matching the filter is being registered. * * Be careful if you use a filter: * If a device does not match the filter when registering, but modifies it's properties later to match the filter, * then the first signal you will see this device in will be ServiceModified. */ void ServiceRegistered(mitk::ServiceReference); /** *\brief Emitted directly before a Service matching the filter is being unregistered. */ void ServiceUnregistering(mitk::ServiceReference); /** *\brief Emitted when a Service matching the filter changes it's properties, or when a service that formerly not matched the filter * changed it's properties and now matches the filter. */ void ServiceModified(mitk::ServiceReference); /** *\brief Emitted when a Service matching the filter changes it's properties, * * and the new properties make it fall trough the filter. This effectively means that * the widget will not track the service anymore. Usually, the Service should still be useable though */ void ServiceModifiedEndMatch(mitk::ServiceReference); /** *\brief Emitted if the user selects a Service from the list. * * If no service is selected, an invalid serviceReference is returned. The user can easily check for this. * if (serviceReference) will evaluate to false, if the reference is invalid and true if valid. */ void ServiceSelectionChanged(mitk::ServiceReference); public slots: protected slots: /** \brief Called, when the selection in the list of Services changes. */ void OnServiceSelectionChanged(); protected: Ui::QmitkServiceListWidgetControls* m_Controls; ///< member holding the UI elements of this widget /** * \brief Internal structure used to link ServiceReferences to their QListWidgetItems */ struct ServiceListLink { mitk::ServiceReference service; QListWidgetItem* item; }; /** * \brief Finishes initialization after Initialize has been called. * * This function assumes that m_Interface is set correctly (Which Initialize does). */ void InitPrivate(const std::string& namingProperty, const std::string& filter); /** * \brief Contains a list of currently active services and their entires in the list. This is wiped with every ServiceRegistryEvent. */ std::vector m_ListContent; /** * \brief Constructs a ListItem from the given service, displays it, and locally stores the service. */ QListWidgetItem* AddServiceToList(mitk::ServiceReference serviceRef); /** * \brief Removes the given service from the list and cleans up. Returns true if successful, false if service was not found. */ bool RemoveServiceFromList(mitk::ServiceReference serviceRef); /** * \brief Returns the serviceReference corresponding to the given ListEntry or an invalid one if none was found (will evaluate to false in bool expressions). */ mitk::ServiceReference GetServiceForListItem(QListWidgetItem* item); /** * \brief Returns a list of ServiceReferences matching the filter criteria by querying the service registry. */ std::list GetAllRegisteredServices(); }; #endif // _QmitkServiceListWidget_H_INCLUDED diff --git a/Modules/Qmitk/QmitkSliderLevelWindowWidget.h b/Modules/Qmitk/QmitkSliderLevelWindowWidget.h index b43d32922a..b3663fa1a6 100644 --- a/Modules/Qmitk/QmitkSliderLevelWindowWidget.h +++ b/Modules/Qmitk/QmitkSliderLevelWindowWidget.h @@ -1,183 +1,195 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKSLIDERLEVELWINDOW_WIDGET #define QMITKSLIDERLEVELWINDOW_WIDGET #include #include #include class QmitkLevelWindowWidgetContextMenu; /** - \class QmitkSliderLevelWindowWidget QmitkSliderLevelWindowWidget.h QmitkSliderLevelWindowWidget.h - \ingroup Widgets - - \brief Provides a widget with a slider to change the level and window value of the current image. - - This documentation actually refers to the QmitkLevelWindowWidget and is only put in this class due to technical issues (should be moved later). - - The QmitkLevelWindowWidget is a kind of container for a - QmitkSliderLevelWindowWidget (this is the cyan bar above the text input - fields) and a QmitkLineEditLevelWindowWidget (with two text input fields). It holds a reference to a - mitk::LevelWindowManager variable, which keeps the LevelWindowProperty of the currently selected image. - Level/Window is manipulated by the text inputs and the Slider to adjust brightness/contrast of a single image. - All changes on the slider or in the text input fields affect the current image by giving new values to LevelWindowManager. - LevelWindowManager then sends a signal to tell other listeners about changes. - - Which image is changed is determined by mitkLevelWindowManager. If m_AutoTopMost is true, always the topmost image - in data tree (layer property) is affected by changes. - The image which is affected by changes can also be changed by QmitkLevelWindowWidgetContextMenu, the context menu - for QmitkSliderLevelWindowWidget and QmitkLineEditLevelWindowWidget. There you have the possibility to set - a certain image or always the topmost image in the data tree (layer property) to be affected by changes. - - The internal mitk::LevelWindow variable contains a range that is valid for - a given image. It should not be possible to move the level/window - parameters outside this range. The range can be changed and reset to its default values - by QmitkLevelWindowWidgetContextMenu, the context menu for QmitkSliderLevelWindowWidget and - QmitkLineEditLevelWindowWidget. - - Now for the behaviour of the text inputs: The upper one contains the - value of the level (brightness), the lower one shows the window (contrast). - - The behaviour of the cyan bar is more obvious: the scale in the background shows the valid range. - The cyan bar in front displays the currently selected level/window setting. - You can change the level by dragging the bar with the left mouse button or clicking somewhere inside the scalerange with the left mouse button. - The window is changed by moving the mouse on the upper or lower bound of the bar until the cursor becomes an vertical double-arrowed symbol. - Then you can change the windowsize by clicking the left mouse button and move the mouse upwards or downwards. - The bar becomes greater upwards as well as downwards. If you want to change the size of the window in only one - direction you have to press the CTRL-key while doing the same as mentioned above. - This information is also presented by a tooltip text when moving the mouse on the upper or lower bound of the bar. - - */ - + * \ingroup QmitkModule + * + * \brief Provides a widget with a slider to change the level and + * window value of the current image. + * + * This documentation actually refers to the QmitkLevelWindowWidget + * and is only put in this class due to technical issues (should be + * moved later). + * + * The QmitkLevelWindowWidget is a kind of container for a + * QmitkSliderLevelWindowWidget (this is the cyan bar above the text + * input fields) and a QmitkLineEditLevelWindowWidget (with two text + * input fields). It holds a reference to a mitk::LevelWindowManager + * variable, which keeps the LevelWindowProperty of the currently + * selected image. Level/Window is manipulated by the text inputs and + * the Slider to adjust brightness/contrast of a single image. All + * changes on the slider or in the text input fields affect the current + * image by giving new values to LevelWindowManager. LevelWindowManager + * then sends a signal to tell other listeners about changes. + * + * Which image is changed is determined by mitkLevelWindowManager. If + * m_AutoTopMost is true, always the topmost image in data tree (layer + * property) is affected by changes. The image which is affected by + * changes can also be changed by QmitkLevelWindowWidgetContextMenu, + * the context menu for QmitkSliderLevelWindowWidget and + * QmitkLineEditLevelWindowWidget. There you have the possibility to + * set a certain image or always the topmost image in the data tree + * (layer property) to be affected by changes. + * + * The internal mitk::LevelWindow variable contains a range that is + * valid for a given image. It should not be possible to move the + * level/window parameters outside this range. The range can be changed + * and reset to its default values by QmitkLevelWindowWidgetContextMenu, + * the context menu for QmitkSliderLevelWindowWidget and + * QmitkLineEditLevelWindowWidget. + * + * Now for the behaviour of the text inputs: The upper one contains the + * value of the level (brightness), the lower one shows the window (contrast). + * + * The behaviour of the cyan bar is more obvious: the scale in the + * background shows the valid range. The cyan bar in front displays the + * currently selected level/window setting. You can change the level by + * dragging the bar with the left mouse button or clicking somewhere inside + * the scalerange with the left mouse button. The window is changed by + * moving the mouse on the upper or lower bound of the bar until the cursor + * becomes an vertical double-arrowed symbol. Then you can change the + * windowsize by clicking the left mouse button and move the mouse upwards + * or downwards. The bar becomes greater upwards as well as downwards. If + * you want to change the size of the window in only one direction you + * have to press the CTRL-key while doing the same as mentioned above. + * This information is also presented by a tooltip text when moving the + * mouse on the upper or lower bound of the bar. + */ class QMITK_EXPORT QmitkSliderLevelWindowWidget : public QWidget { Q_OBJECT public: /// constructor QmitkSliderLevelWindowWidget( QWidget * parent=0, Qt::WindowFlags f = 0 ); /// destructor ~QmitkSliderLevelWindowWidget(); /*! * data structure which stores the values manipulated * by a QmitkSliderLevelWindowWidget */ mitk::LevelWindow m_LevelWindow; /// manager who is responsible to collect and deliver changes on Level/Window mitk::LevelWindowManager::Pointer m_Manager; /// sets the manager who is responsible to collect and deliver changes on Level/Window void setLevelWindowManager(mitk::LevelWindowManager* levelWindowManager); /// sets the DataStorage which holds all image-nodes void setDataStorage(mitk::DataStorage* ds); /// returns the manager who is responsible to collect and deliver changes on Level/Window mitk::LevelWindowManager* GetManager(); private: /// creates the contextmenu for this widget from class QmitkLevelWindowWidgetContextMenu void contextMenuEvent ( QContextMenuEvent * ); /// change notifications from the mitkLevelWindowManager void OnPropertyModified(const itk::EventObject& e); protected: /// recalculate the size and position of the slider bar virtual void update( ); /*! * helper for drawing the component */ QRect m_Rect; /*! * helper for drawing the component */ QPoint m_StartPos; bool m_Resize; bool m_Bottom; bool m_MouseDown; bool m_Leftbutton; bool m_CtrlPressed; int m_MoveHeight; bool m_ScaleVisible; QRect m_LowerBound; QRect m_UpperBound; unsigned long m_ObserverTag; bool m_IsObserverTagSet; QFont m_Font; /*! * data structure which creates the contextmenu for QmitkLineEditLevelWindowWidget */ QmitkLevelWindowWidgetContextMenu* m_Contextmenu; /*! * repaint the slider and the scale */ void paintEvent( QPaintEvent* e ); /*! * method implements the component behaviour * * checks if cursor is on upper or lower bound of slider bar and changes cursor symbol * * checks if left mouse button is pressed and if CTRL is pressed and changes sliderbar in movedirection accordingly */ void mouseMoveEvent( QMouseEvent* mouseEvent ); void enterEvent ( QEvent * event ); /*! * registers events when a mousebutton is pressed * * if leftbutton is pressed m_Leftbutton is set to true * * also checks if CTRL is pressed and sets the bool variable m_CtrlPressed */ void mousePressEvent( QMouseEvent* mouseEvent ); /*! * sets the variable m_MouseDown to false */ void mouseReleaseEvent( QMouseEvent* mouseEvent ); /*! * causes an update of the sliderbar when resizing the window */ void virtual resizeEvent ( QResizeEvent * event ); protected slots: /// hides the scale if "Hide Scale" is selected in contextmenu void hideScale(); /// shows the scale if "Show Scale" is selected in contextmenu void showScale(); }; #endif //QMITKSLIDERLEVELWINDOW_WIDGET diff --git a/Modules/Qmitk/QmitkStdMultiWidget.h b/Modules/Qmitk/QmitkStdMultiWidget.h index 2daaa8866b..e68e3ec9d4 100644 --- a/Modules/Qmitk/QmitkStdMultiWidget.h +++ b/Modules/Qmitk/QmitkStdMultiWidget.h @@ -1,359 +1,360 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKSTDMULTIWIDGET_H_ #define QMITKSTDMULTIWIDGET_H_ #include #include "mitkPositionTracker.h" #include "mitkSlicesRotator.h" #include "mitkSlicesSwiveller.h" #include "mitkRenderWindowFrame.h" #include "mitkManufacturerLogo.h" #include "mitkGradientBackground.h" #include "mitkCoordinateSupplier.h" #include "mitkDataStorage.h" #include "mitkMouseModeSwitcher.h" #include #include #include #include #include #include "vtkTextProperty.h" #include "vtkCornerAnnotation.h" class QHBoxLayout; class QVBoxLayout; class QGridLayout; class QSpacerItem; class QmitkLevelWindowWidget; class QmitkRenderWindow; namespace mitk { class RenderingManager; } +/// \ingroup QmitkModule class QMITK_EXPORT QmitkStdMultiWidget : public QWidget { Q_OBJECT public: QmitkStdMultiWidget(QWidget* parent = 0, Qt::WindowFlags f = 0, mitk::RenderingManager* renderingManager = 0); virtual ~QmitkStdMultiWidget(); mitk::SliceNavigationController* GetTimeNavigationController(); void RequestUpdate(); void ForceImmediateUpdate(); mitk::MouseModeSwitcher* GetMouseModeSwitcher(); QmitkRenderWindow* GetRenderWindow1() const; QmitkRenderWindow* GetRenderWindow2() const; QmitkRenderWindow* GetRenderWindow3() const; QmitkRenderWindow* GetRenderWindow4() const; const mitk::Point3D & GetLastLeftClickPosition() const; const mitk::Point3D GetCrossPosition() const; void EnablePositionTracking(); void DisablePositionTracking(); int GetLayout() const; mitk::SlicesRotator * GetSlicesRotator() const; mitk::SlicesSwiveller * GetSlicesSwiveller() const; bool GetGradientBackgroundFlag() const; /*! \brief Access node of widget plane 1 \return DataNode holding widget plane 1 */ mitk::DataNode::Pointer GetWidgetPlane1(); /*! \brief Access node of widget plane 2 \return DataNode holding widget plane 2 */ mitk::DataNode::Pointer GetWidgetPlane2(); /*! \brief Access node of widget plane 3 \return DataNode holding widget plane 3 */ mitk::DataNode::Pointer GetWidgetPlane3(); /*! \brief Convenience method to access node of widget planes \param id number of widget plane to be returned \return DataNode holding widget plane 3 */ mitk::DataNode::Pointer GetWidgetPlane(int id); bool IsColoredRectanglesEnabled() const; bool IsDepartmentLogoEnabled() const; bool IsCrosshairNavigationEnabled() const; void InitializeWidget(); /// called when the StdMultiWidget is closed to remove the 3 widget planes and the helper node from the DataStorage void RemovePlanesFromDataStorage(); void AddPlanesToDataStorage(); void SetDataStorage( mitk::DataStorage* ds ); /** \brief Listener to the CrosshairPositionEvent Ensures the CrosshairPositionEvent is handled only once and at the end of the Qt-Event loop */ void HandleCrosshairPositionEvent(); /// activate Menu Widget. true: activated, false: deactivated void ActivateMenuWidget( bool state ); bool IsMenuWidgetEnabled() const; protected: void UpdateAllWidgets(); void HideAllWidgetToolbars(); public slots: /// Receives the signal from HandleCrosshairPositionEvent, executes the StatusBar update void HandleCrosshairPositionEventDelayed(); void changeLayoutTo2DImagesUp(); void changeLayoutTo2DImagesLeft(); void changeLayoutToDefault(); void changeLayoutToBig3D(); void changeLayoutToWidget1(); void changeLayoutToWidget2(); void changeLayoutToWidget3(); void changeLayoutToRowWidget3And4(); void changeLayoutToColumnWidget3And4(); void changeLayoutToRowWidgetSmall3andBig4(); void changeLayoutToSmallUpperWidget2Big3and4(); void changeLayoutTo2x2Dand3DWidget(); void changeLayoutToLeft2Dand3DRight2D(); void changeLayoutTo2DUpAnd3DDown(); void Fit(); void InitPositionTracking(); void AddDisplayPlaneSubTree(); void EnableStandardLevelWindow(); void DisableStandardLevelWindow(); bool InitializeStandardViews( const mitk::Geometry3D * geometry ); void wheelEvent( QWheelEvent * e ); void mousePressEvent(QMouseEvent * e); void moveEvent( QMoveEvent* e ); void leaveEvent ( QEvent * e ); void EnsureDisplayContainsPoint( mitk::DisplayGeometry* displayGeometry, const mitk::Point3D& p); void MoveCrossToPosition(const mitk::Point3D& newPosition); void EnableNavigationControllerEventListening(); void DisableNavigationControllerEventListening(); void EnableGradientBackground(); void DisableGradientBackground(); void EnableDepartmentLogo(); void DisableDepartmentLogo(); void EnableColoredRectangles(); void DisableColoredRectangles(); void SetWidgetPlaneVisibility(const char* widgetName, bool visible, mitk::BaseRenderer *renderer=NULL); void SetWidgetPlanesVisibility(bool visible, mitk::BaseRenderer *renderer=NULL); void SetWidgetPlanesLocked(bool locked); void SetWidgetPlanesRotationLocked(bool locked); void SetWidgetPlanesRotationLinked( bool link ); void SetWidgetPlaneMode( int mode ); void SetGradientBackgroundColors( const mitk::Color & upper, const mitk::Color & lower ); void SetDepartmentLogoPath( const char * path ); void SetWidgetPlaneModeToSlicing( bool activate ); void SetWidgetPlaneModeToRotation( bool activate ); void SetWidgetPlaneModeToSwivel( bool activate ); void OnLayoutDesignChanged( int layoutDesignIndex ); void ResetCrosshair(); void MouseModeSelected( mitk::MouseModeSwitcher::MouseMode mouseMode ); signals: void LeftMouseClicked(mitk::Point3D pointValue); void WheelMoved(QWheelEvent*); void WidgetPlanesRotationLinked(bool); void WidgetPlanesRotationEnabled(bool); void ViewsInitialized(); void WidgetPlaneModeSlicing(bool); void WidgetPlaneModeRotation(bool); void WidgetPlaneModeSwivel(bool); void WidgetPlaneModeChange(int); void WidgetNotifyNewCrossHairMode(int); void Moved(); public: /** Define RenderWindow (public)*/ QmitkRenderWindow* mitkWidget1; QmitkRenderWindow* mitkWidget2; QmitkRenderWindow* mitkWidget3; QmitkRenderWindow* mitkWidget4; QmitkLevelWindowWidget* levelWindowWidget; /********************************/ enum { PLANE_MODE_SLICING = 0, PLANE_MODE_ROTATION, PLANE_MODE_SWIVEL }; enum { LAYOUT_DEFAULT = 0, LAYOUT_2D_IMAGES_UP, LAYOUT_2D_IMAGES_LEFT, LAYOUT_BIG_3D, LAYOUT_WIDGET1, LAYOUT_WIDGET2, LAYOUT_WIDGET3, LAYOUT_2X_2D_AND_3D_WIDGET, LAYOUT_ROW_WIDGET_3_AND_4, LAYOUT_COLUMN_WIDGET_3_AND_4, LAYOUT_ROW_WIDGET_SMALL3_AND_BIG4 , LAYOUT_SMALL_UPPER_WIDGET2_BIG3_AND4,LAYOUT_2D_AND_3D_LEFT_2D_RIGHT_WIDGET, LAYOUT_2D_UP_AND_3D_DOWN}; enum { TRANSVERSAL, AXIAL = TRANSVERSAL, SAGITTAL, CORONAL, THREE_D }; protected: QHBoxLayout* QmitkStdMultiWidgetLayout; int m_Layout; int m_PlaneMode; mitk::RenderingManager* m_RenderingManager; mitk::RenderWindowFrame::Pointer m_RectangleRendering3; mitk::RenderWindowFrame::Pointer m_RectangleRendering2; mitk::RenderWindowFrame::Pointer m_RectangleRendering1; mitk::RenderWindowFrame::Pointer m_RectangleRendering4; mitk::ManufacturerLogo::Pointer m_LogoRendering1; mitk::ManufacturerLogo::Pointer m_LogoRendering2; mitk::ManufacturerLogo::Pointer m_LogoRendering3; mitk::ManufacturerLogo::Pointer m_LogoRendering4; mitk::GradientBackground::Pointer m_GradientBackground1; mitk::GradientBackground::Pointer m_GradientBackground2; mitk::GradientBackground::Pointer m_GradientBackground4; mitk::GradientBackground::Pointer m_GradientBackground3; bool m_GradientBackgroundFlag; mitk::MouseModeSwitcher::Pointer m_MouseModeSwitcher; mitk::CoordinateSupplier::Pointer m_LastLeftClickPositionSupplier; mitk::PositionTracker::Pointer m_PositionTracker; mitk::SliceNavigationController* m_TimeNavigationController; mitk::SlicesRotator::Pointer m_SlicesRotator; mitk::SlicesSwiveller::Pointer m_SlicesSwiveller; mitk::DataNode::Pointer m_PositionTrackerNode; mitk::DataStorage::Pointer m_DataStorage; mitk::DataNode::Pointer m_PlaneNode1; mitk::DataNode::Pointer m_PlaneNode2; mitk::DataNode::Pointer m_PlaneNode3; mitk::DataNode::Pointer m_Node; QSplitter *m_MainSplit; QSplitter *m_LayoutSplit; QSplitter *m_SubSplit1; QSplitter *m_SubSplit2; QWidget *mitkWidget1Container; QWidget *mitkWidget2Container; QWidget *mitkWidget3Container; QWidget *mitkWidget4Container; struct { vtkCornerAnnotation *cornerText; vtkTextProperty *textProp; vtkRenderer *ren; } m_CornerAnnotaions[3]; bool m_PendingCrosshairPositionEvent; bool m_CrosshairNavigationEnabled; }; #endif /*QMITKSTDMULTIWIDGET_H_*/ diff --git a/Modules/QmitkExt/QmitkPointListView.cpp b/Modules/QmitkExt/QmitkPointListView.cpp index fb35fe6376..6085eb1b95 100644 --- a/Modules/QmitkExt/QmitkPointListView.cpp +++ b/Modules/QmitkExt/QmitkPointListView.cpp @@ -1,443 +1,470 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkPointListView.h" #include "QmitkPointListModel.h" #include "QmitkStdMultiWidget.h" #include "QmitkEditPointDialog.h" #include "mitkRenderingManager.h" #include #include #include #include #include QmitkPointListView::QmitkPointListView( QWidget* parent ) - :QListView( parent ), - m_PointListModel( new QmitkPointListModel() ), - m_SelfCall( false ), - m_showFading(false), - m_MultiWidget( NULL), - m_Snc1(NULL), - m_Snc2(NULL), - m_Snc3(NULL) + : QListView( parent ), + m_Snc1(NULL), + m_Snc2(NULL), + m_Snc3(NULL), + m_PointListModel( new QmitkPointListModel() ), + m_SelfCall( false ), + m_showFading(false), + m_MultiWidget( NULL) { QListView::setAlternatingRowColors( true ); // logic QListView::setSelectionBehavior( QAbstractItemView::SelectRows ); QListView::setSelectionMode( QAbstractItemView::SingleSelection ); QListView::setModel( m_PointListModel ); QString tooltip = QString("Use the F2/F3 keys to move a point up/down, the Del key to remove a point\nand the mouse wheel to change the timestep.\n\nTimeStep:\t%1").arg(0); QListView::setToolTip(tooltip); //m_FadeTimer = new QTimer(); this->setContextMenuPolicy(Qt::CustomContextMenu); m_TimeStepFaderLabel = new QLabel(this); QFont font("Arial", 17); m_TimeStepFaderLabel->setFont(font); //Define Size this->setMinimumHeight(40); //horizontal, vertical this->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); //connect connect( m_PointListModel, SIGNAL(SignalUpdateSelection()), this, SLOT(OnPointSetSelectionChanged()) ); connect( this, SIGNAL(doubleClicked ( const QModelIndex & )), this, SLOT(OnPointDoubleClicked( const QModelIndex & )) ); connect( QListView::selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(OnListViewSelectionChanged(const QItemSelection& , const QItemSelection&)) ); connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(ctxMenu(const QPoint &))); } QmitkPointListView::~QmitkPointListView() { delete m_PointListModel; } void QmitkPointListView::SetPointSetNode( mitk::DataNode* pointSetNode ) { m_PointListModel->SetPointSetNode( pointSetNode); } const mitk::PointSet* QmitkPointListView::GetPointSet() const { return m_PointListModel->GetPointSet(); } void QmitkPointListView::SetMultiWidget( QmitkStdMultiWidget* multiWidget ) { m_MultiWidget = multiWidget; } QmitkStdMultiWidget* QmitkPointListView::GetMultiWidget() const { return m_MultiWidget; } void QmitkPointListView::OnPointDoubleClicked(const QModelIndex & index) { mitk::PointSet::PointType p; mitk::PointSet::PointIdentifier id; m_PointListModel->GetPointForModelIndex(index, p, id); QmitkEditPointDialog _EditPointDialog(this); _EditPointDialog.SetPoint(m_PointListModel->GetPointSet(), id, m_PointListModel->GetTimeStep()); _EditPointDialog.exec(); } void QmitkPointListView::OnPointSetSelectionChanged() { const mitk::PointSet* pointSet = m_PointListModel->GetPointSet(); if (pointSet == NULL) return; // update this view's selection status as a result to changes in the point set data structure m_SelfCall = true; int timeStep = m_PointListModel->GetTimeStep(); if ( pointSet->GetNumberOfSelected( timeStep ) > 1 ) { MITK_ERROR << "Point set has multiple selected points. This view is not designed for more than one selected point."; } int selectedIndex = pointSet->SearchSelectedPoint( timeStep ); if (selectedIndex == -1) // no selected point is found { m_SelfCall = false; return; } QModelIndex index; bool modelIndexOkay = m_PointListModel->GetModelIndexForPointID(selectedIndex, index); if (modelIndexOkay == true) QListView::selectionModel()->select( index , QItemSelectionModel::ClearAndSelect ); emit SignalPointSelectionChanged(); m_SelfCall = false; } void QmitkPointListView::OnListViewSelectionChanged(const QItemSelection& selected, const QItemSelection& /*deselected*/) { if (m_SelfCall) return; mitk::PointSet* pointSet = const_cast( m_PointListModel->GetPointSet() ); if (pointSet == NULL) return; // (take care that this widget doesn't react to self-induced changes by setting m_SelfCall) m_SelfCall = true; // update selection of all points in pointset: select the one(s) that are selected in the view, deselect all others QModelIndexList selectedIndexes = selected.indexes(); for (mitk::PointSet::PointsContainer::Iterator it = pointSet->GetPointSet(m_PointListModel->GetTimeStep())->GetPoints()->Begin(); it != pointSet->GetPointSet(m_PointListModel->GetTimeStep())->GetPoints()->End(); ++it) { QModelIndex index; if (m_PointListModel->GetModelIndexForPointID(it->Index(), index)) { if (selectedIndexes.indexOf(index) != -1) // index is found in the selected indices list { pointSet->SetSelectInfo(it->Index(), true, m_PointListModel->GetTimeStep()); // Use Multiwidget or SliceNavigationControllers to set crosshair to selected point if ( m_MultiWidget != NULL) { m_MultiWidget->MoveCrossToPosition(pointSet->GetPoint(it->Index(), m_PointListModel->GetTimeStep())); } - else if ( (m_Snc1 != NULL) && (m_Snc2 != NULL) && (m_Snc3 != NULL) ) + + mitk::Point3D p = pointSet->GetPoint(it->Index(), m_PointListModel->GetTimeStep()); + + // remove the three ifs below after the SetSnc* methods have been removed + if (m_Snc1 != NULL) { - mitk::Point3D p = pointSet->GetPoint(it->Index(), m_PointListModel->GetTimeStep()); m_Snc1->SelectSliceByPoint(p); + } + if (m_Snc2 != NULL) + { m_Snc2->SelectSliceByPoint(p); + } + if (m_Snc3 != NULL) + { m_Snc3->SelectSliceByPoint(p); } + + for (std::set::const_iterator i = m_Sncs.begin(); + i != m_Sncs.end(); ++i) + { + (*i)->SelectSliceByPoint(p); + } } else { pointSet->SetSelectInfo(it->Index(), false, m_PointListModel->GetTimeStep()); } } } m_SelfCall = false; emit SignalPointSelectionChanged(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkPointListView::keyPressEvent( QKeyEvent * e ) { if (m_PointListModel == NULL) return; int key = e->key(); switch (key) { case Qt::Key_F2: m_PointListModel->MoveSelectedPointUp(); break; case Qt::Key_F3: m_PointListModel->MoveSelectedPointDown(); break; case Qt::Key_Delete: m_PointListModel->RemoveSelectedPoint(); break; default: break; } } void QmitkPointListView::wheelEvent(QWheelEvent *event) { if (!m_PointListModel || !m_PointListModel->GetPointSet() || (int)(m_PointListModel->GetPointSet()->GetTimeSteps()) == 1 /*|| !m_4DPointSet*/) return; int whe = event->delta(); mitk::PointSet::Pointer ps = dynamic_cast(m_PointListModel->GetPointSet()); unsigned int numberOfTS = ps->GetTimeSteps(); if(numberOfTS == 1) return; int currentTS = this->m_PointListModel->GetTimeStep(); if(whe > 0) { if((currentTS >= (int)(m_PointListModel->GetPointSet()->GetTimeSteps()))) return; this->m_PointListModel->SetTimeStep(++currentTS); } else { if((currentTS <= 0)) return; this->m_PointListModel->SetTimeStep(--currentTS); } QString tooltip = QString("Use the F2/F3 keys to move a point up/down, the Del key to remove a point\nand the mouse wheel to change the timestep.\n\nTimeStep:\t%1").arg(currentTS); this->setToolTip(tooltip); fadeTimeStepIn(); } void QmitkPointListView::fadeTimeStepIn() { //Setup Widget QWidget *m_TimeStepFader = new QWidget(this); QHBoxLayout *layout = new QHBoxLayout(m_TimeStepFader); int x = (int)(this->geometry().x()+this->width()*0.6); int y = (int)(this->geometry().y()+this->height()*0.8); m_TimeStepFader->move(x,y); m_TimeStepFader->resize(60, 55); m_TimeStepFader->setLayout(layout); m_TimeStepFader->setAttribute(Qt::WA_DeleteOnClose); //setup Label // QLabel *label = new QLabel(QString("%1").arg(this->m_PointListModel->GetTimeStep())); layout->addWidget(m_TimeStepFaderLabel); m_TimeStepFaderLabel->setAlignment(Qt::AlignCenter); m_TimeStepFaderLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); m_TimeStepFaderLabel->setLineWidth(2); m_TimeStepFaderLabel->setText(QString("%1").arg(this->m_PointListModel->GetTimeStep())); //give the widget opacity and some colour QPalette pal = m_TimeStepFaderLabel->palette(); QColor semiTransparentColor(139, 192, 223, 50); QColor labelTransparentColor(0,0,0,200); pal.setColor(m_TimeStepFaderLabel->backgroundRole(), semiTransparentColor); pal.setColor(m_TimeStepFaderLabel->foregroundRole(), labelTransparentColor); m_TimeStepFaderLabel->setAutoFillBackground(true); m_TimeStepFaderLabel->setPalette(pal); //show the widget m_TimeStepFader->show(); //and start the timer m_TimeStepFaderLabel->setVisible(true); QTimer::singleShot(2000, this, SLOT(fadeTimeStepOut())); } void QmitkPointListView::fadeTimeStepOut() { m_TimeStepFaderLabel->hide(); } void QmitkPointListView::ctxMenu(const QPoint &pos) { QMenu *menu = new QMenu; // menu->setStyle(); // menu->addAction(tr("Test Item"), this, SLOT(test_slot())); //add Fading check QAction *showFading = new QAction(this); showFading->setCheckable(false); //TODO: reset when fading is working showFading->setEnabled(false); //TODO: reset when fading is working showFading->setText("Fade TimeStep"); connect(showFading, SIGNAL(triggered(bool)), this, SLOT(SetFading(bool))); menu->addAction(showFading); //add Clear action QAction *clearList = new QAction(this); clearList->setText("Clear List"); connect(clearList, SIGNAL(triggered()), this, SLOT(ClearPointList())); menu->addAction(clearList); //add Clear TimeStep action QAction *clearTS = new QAction(this); clearTS->setText("Clear current time step"); connect(clearTS, SIGNAL(triggered()), this, SLOT(ClearPointListTS())); menu->addAction(clearTS); // //add "show time step in list" option // QAction *viewTS = new QAction(this); // viewTS->setText("Show time step in list"); // viewTS->setCheckable(true); // viewTS->setChecked(false); // connect(viewTS, SIGNAL(triggered(bool)), this, SLOT(ClearPointList(bool))); // menu->addAction(viewTS); menu->exec(this->mapToGlobal(pos)); } void QmitkPointListView::SetFading(bool onOff) { m_showFading = onOff; } void QmitkPointListView::ClearPointList() { if(!m_PointListModel->GetPointSet()) return; mitk::PointSet::Pointer curPS = m_PointListModel->GetPointSet(); if ( curPS->GetSize() == 0) return; switch( QMessageBox::question( this, tr("Clear Points"), tr("Remove all points from the displayed list?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No)) { case QMessageBox::Yes: { // m_PointListModel->ClearList(); // /* // if (curPS) // { // curPS->Clear(); // } // */ // mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // break; mitk::PointSet::PointsIterator it; mitk::PointSet::PointsContainer *curPsPoints; while( !curPS->IsEmptyTimeStep(0)) { curPsPoints = curPS->GetPointSet()->GetPoints(); it = curPsPoints->Begin(); curPS->SetSelectInfo(it->Index(),true); m_PointListModel->RemoveSelectedPoint(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); break; } case QMessageBox::No: default: break; } // emit PointListChanged(); } void QmitkPointListView::ClearPointListTS() { // mitk::PointSet* /*::Pointer*/ curPS = m_PointListModel->GetPointSet(); // if ( curPS->GetSize() == 0) // return; // int ts = this->m_PointListModel->GetTimeStep(); // switch( QMessageBox::question( this, tr("Clear Points in Timestep"), // tr("Remove all points from the list with the timestep %1?").arg(ts), // QMessageBox::Yes | QMessageBox::No, QMessageBox::No)) // { // case QMessageBox::Yes: // if (curPS) // { // mitk::PointSet::DataType::Pointer curPSwithTS = curPS->GetPointSet(ts); // //curPSwithTS->Clear(); // } // mitk::RenderingManager::GetInstance()->RequestUpdateAll(); // break; // case QMessageBox::No: // default: // break; // } // // emit PointListChanged(); } void QmitkPointListView::SetSnc1(mitk::SliceNavigationController* snc) { m_Snc1 = snc; } void QmitkPointListView::SetSnc2(mitk::SliceNavigationController* snc) { m_Snc2 = snc; } void QmitkPointListView::SetSnc3(mitk::SliceNavigationController* snc) { m_Snc3 = snc; -} \ No newline at end of file +} + +void QmitkPointListView::AddSliceNavigationController(mitk::SliceNavigationController* snc) +{ + if (snc == NULL) return; + m_Sncs.insert(snc); +} + +void QmitkPointListView::RemoveSliceNavigationController(mitk::SliceNavigationController* snc) +{ + if (snc == NULL) return; + m_Sncs.erase(snc); +} diff --git a/Modules/QmitkExt/QmitkPointListView.h b/Modules/QmitkExt/QmitkPointListView.h index 6c142c380f..68f5c4a2e3 100644 --- a/Modules/QmitkExt/QmitkPointListView.h +++ b/Modules/QmitkExt/QmitkPointListView.h @@ -1,131 +1,153 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITK_POINTLIST_VIEW_H_INCLUDED #define QMITK_POINTLIST_VIEW_H_INCLUDED #include #include #include "QmitkExtExports.h" #include #include "QmitkPointListModel.h" class QmitkStdMultiWidget; /*! * \brief GUI widget for handling mitk::PointSet * * Displays all the points in a mitk::PointSet graphically. * Reacts automatically to changes in the PointSet's selection status. * Updates PointSet's selection status when this list's selection changes. * * If a QmitkStdMultiWidget is assigned via SetMultiWidget(), the * crosshair of the QmitkStdMultiWidget is moved to the currently selected * point. * */ class QmitkExt_EXPORT QmitkPointListView : public QListView { Q_OBJECT public: QmitkPointListView( QWidget* parent = 0 ); ~QmitkPointListView(); /// assign a point set for observation void SetPointSetNode( mitk::DataNode* pointSetNode ); /// which point set to work on const mitk::PointSet* GetPointSet() const; /** * \brief If Multiwidget is set, the crosshair is automatically centering to the selected point * As an alternative, if you dont have a multiwidget, you can call SetSnc1, SetSnc2, SetSnc3 to set the * SliceNavigationControllers directly to enable the focussing feature. */ void SetMultiWidget( QmitkStdMultiWidget* multiWidget ); QmitkStdMultiWidget* GetMultiWidget() const; ///< return the QmitkStdMultiWidget that is used for updating render window crosshair void SetTimesStep(int i); ///< which time step to display/model ///@{ /** * \brief Sets the SliceNavigationController of the three 2D Renderwindows. * If they are defined, they can be used to automatically set the crosshair to the selected point + * + * \deprecatedSince{2013_03} Use AddSliceNavigationController and RemoveSliceNavigationController instead. */ - void SetSnc1(mitk::SliceNavigationController* snc); - void SetSnc2(mitk::SliceNavigationController* snc); - void SetSnc3(mitk::SliceNavigationController* snc); + DEPRECATED( void SetSnc1(mitk::SliceNavigationController* snc) ); + DEPRECATED( void SetSnc2(mitk::SliceNavigationController* snc) ); + DEPRECATED( void SetSnc3(mitk::SliceNavigationController* snc) ); ///@} + /** + * @brief Add a mitk::SliceNavigationController instance. + * @param snc The mitk::SliceNavigationController instance. + * + * This method adds \c snc to the set of slice navigation controllers which are + * used to navigate to the selected point. + */ + void AddSliceNavigationController(mitk::SliceNavigationController* snc); + + /** + * @brief Remove a mitk::SliceNavigationController instance. + * @param snc The mitk::SliceNavigationController instance. + * + * This method removes \c snc from the set of slice navigation controllers which are + * used to navigate to the selected point. + */ + void RemoveSliceNavigationController(mitk::SliceNavigationController* snc); + signals: void SignalPointSelectionChanged(); ///< this signal is emmitted, if the selection of a point in the pointset is changed protected slots: /// Filtering double click event for editing point coordinates via a dialog void OnPointDoubleClicked(const QModelIndex & index); /// called when the point set data structure changes void OnPointSetSelectionChanged(); /// called when the selection of the view widget changes void OnListViewSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); /// fade the shown timestep out void fadeTimeStepOut(); /// open ContextMenu void ctxMenu(const QPoint &pos); /// Turn TimeStep Fading On/Off void SetFading(bool onOff); /// Delete all points in the list void ClearPointList(); /// delete all points in the list in the current timestep void ClearPointListTS(); protected: void keyPressEvent( QKeyEvent * e ); ///< react to F2, F3 and DEL keys void wheelEvent( QWheelEvent* event); ///< change timestep of the current pointset by mouse wheel void fadeTimeStepIn(); ///< fade a label with the currently shown timestep in mitk::SliceNavigationController* m_Snc1; mitk::SliceNavigationController* m_Snc2; mitk::SliceNavigationController* m_Snc3; + std::set m_Sncs; + QmitkPointListModel* m_PointListModel; bool m_SelfCall; bool m_showFading; /// used to position the planes on a selected point QmitkStdMultiWidget* m_MultiWidget; QLabel* m_TimeStepFaderLabel; }; #endif diff --git a/Modules/QmitkExt/QmitkPointListWidget.cpp b/Modules/QmitkExt/QmitkPointListWidget.cpp index 8b07f95800..ff6e60b88e 100644 --- a/Modules/QmitkExt/QmitkPointListWidget.cpp +++ b/Modules/QmitkExt/QmitkPointListWidget.cpp @@ -1,471 +1,506 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkPointListWidget.h" #include #include #include #include #include #include #include #include #include "btnLoad.xpm" #include "btnSave.xpm" #include "btnClear.xpm" #include "btnSetPoints.xpm" #include "btnSetPointsManually.xpm" #include "btnUp.xpm" #include "btnDown.xpm" QmitkPointListWidget::QmitkPointListWidget(QWidget *parent, int orientation): QWidget(parent), m_PointListView(NULL), m_MultiWidget(NULL), m_PointSetNode(NULL), m_Orientation(0), m_MovePointUpBtn(NULL), m_MovePointDownBtn(NULL), m_RemovePointBtn(NULL), m_SavePointsBtn(NULL), m_LoadPointsBtn(NULL), m_ToggleAddPoint(NULL), - m_AddPoint(NULL), m_Interactor(NULL), m_TimeStep(0), m_EditAllowed(true), m_NodeObserverTag(0), + m_AddPoint(NULL), m_Snc1(NULL), m_Snc2(NULL), - m_Snc3(NULL) + m_Snc3(NULL), + m_Interactor(NULL), + m_TimeStep(0), + m_EditAllowed(true), + m_NodeObserverTag(0) { m_PointListView = new QmitkPointListView(); if(orientation != 0) m_Orientation = orientation; SetupUi(); SetupConnections(); ObserveNewNode(NULL); } QmitkPointListWidget::~QmitkPointListWidget() { if (m_Interactor) mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; if(m_PointSetNode && m_NodeObserverTag) { m_PointSetNode->RemoveObserver(m_NodeObserverTag); m_NodeObserverTag = 0; } m_MultiWidget = NULL; delete m_PointListView; } void QmitkPointListWidget::SetupConnections() { //m_PointListView->setModel(m_PointListModel); connect(this->m_LoadPointsBtn, SIGNAL(clicked()), this, SLOT(OnBtnLoadPoints())); connect(this->m_SavePointsBtn, SIGNAL(clicked()), this, SLOT(OnBtnSavePoints())); connect(this->m_MovePointUpBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointUp())); connect(this->m_MovePointDownBtn, SIGNAL(clicked()), this, SLOT(MoveSelectedPointDown())); connect(this->m_RemovePointBtn, SIGNAL(clicked()), this, SLOT(RemoveSelectedPoint())); connect(this->m_ToggleAddPoint, SIGNAL(toggled(bool)), this, SLOT(OnBtnAddPoint(bool))); connect(this->m_AddPoint, SIGNAL(clicked()), this, SLOT(OnBtnAddPointManually())); connect(this->m_PointListView, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(OnListDoubleClick())); connect(this->m_PointListView, SIGNAL(SignalPointSelectionChanged()), this, SLOT(OnPointSelectionChanged())); } void QmitkPointListWidget::SetupUi() { //Setup the buttons m_ToggleAddPoint = new QPushButton();//iconSetPoints, "", this); m_ToggleAddPoint->setMaximumSize(25,25); m_ToggleAddPoint->setCheckable(true); m_ToggleAddPoint->setToolTip("Toggle point editing (use SHIFT + Left Mouse Button to add Points)"); QIcon iconAdd(btnSetPoints_xpm); m_ToggleAddPoint->setIcon(iconAdd); m_AddPoint = new QPushButton();//iconSetPoints, "", this); m_AddPoint->setMaximumSize(25,25); m_AddPoint->setToolTip("Manually add point"); QIcon iconAddManually(btnSetPointsManually_xpm); m_AddPoint->setIcon(iconAddManually); m_RemovePointBtn = new QPushButton(); m_RemovePointBtn->setMaximumSize(25, 25); const QIcon iconDel(btnClear_xpm); m_RemovePointBtn->setIcon(iconDel); m_RemovePointBtn->setToolTip("Erase one point from list (Hotkey: DEL)"); m_MovePointUpBtn = new QPushButton(); m_MovePointUpBtn->setMaximumSize(25, 25); const QIcon iconUp(btnUp_xpm); m_MovePointUpBtn->setIcon(iconUp); m_MovePointUpBtn->setToolTip("Swap selected point upwards (Hotkey: F2)"); m_MovePointDownBtn = new QPushButton(); m_MovePointDownBtn->setMaximumSize(25, 25); const QIcon iconDown(btnDown_xpm); m_MovePointDownBtn->setIcon(iconDown); m_MovePointDownBtn->setToolTip("Swap selected point downwards (Hotkey: F3)"); m_SavePointsBtn = new QPushButton(); m_SavePointsBtn->setMaximumSize(25, 25); QIcon iconSave(btnSave_xpm); m_SavePointsBtn->setIcon(iconSave); m_SavePointsBtn->setToolTip("Save points to file"); m_LoadPointsBtn = new QPushButton(); m_LoadPointsBtn->setMaximumSize(25, 25); QIcon iconLoad(btnLoad_xpm); m_LoadPointsBtn->setIcon(iconLoad); m_LoadPointsBtn->setToolTip("Load list of points from file (REPLACES current content)"); int i; QBoxLayout* lay1; QBoxLayout* lay2; switch (m_Orientation) { case 0: lay1 = new QVBoxLayout(this); lay2 = new QHBoxLayout(); i = 0; break; case 1: lay1 = new QHBoxLayout(this); lay2 = new QVBoxLayout(); i=-1; break; case 2: lay1 = new QHBoxLayout(this); lay2 = new QVBoxLayout(); i=0; break; default: lay1 = new QVBoxLayout(this); lay2 = new QHBoxLayout(); i=-1; break; } //setup Layouts this->setLayout(lay1); lay1->addLayout(lay2); lay2->stretch(true); lay2->addWidget(m_ToggleAddPoint); lay2->addWidget(m_AddPoint); lay2->addWidget(m_RemovePointBtn); lay2->addWidget(m_MovePointUpBtn); lay2->addWidget(m_MovePointDownBtn); lay2->addWidget(m_SavePointsBtn); lay2->addWidget(m_LoadPointsBtn); //lay2->addSpacing();; lay1->insertWidget(i,m_PointListView); this->setLayout(lay1); } void QmitkPointListWidget::SetPointSet(mitk::PointSet* newPs) { if(newPs == NULL) return; this->m_PointSetNode->SetData(newPs); dynamic_cast(this->m_PointListView->model())->SetPointSetNode(m_PointSetNode); ObserveNewNode(m_PointSetNode); } void QmitkPointListWidget::SetPointSetNode(mitk::DataNode *newNode) { ObserveNewNode(newNode); dynamic_cast(this->m_PointListView->model())->SetPointSetNode(newNode); } void QmitkPointListWidget::OnBtnSavePoints() { if ((dynamic_cast(m_PointSetNode->GetData())) == NULL) return; // don't write empty point sets. If application logic requires something else then do something else. if ((dynamic_cast(m_PointSetNode->GetData()))->GetSize() == 0) return; // let the user choose a file std::string name(""); QString fileNameProposal = QString("/PointSet.mps");//.arg(m_PointSetNode->GetName().c_str()); //"PointSet.mps"; QString aFilename = QFileDialog::getSaveFileName( NULL, "Save point set", QDir::currentPath() + fileNameProposal, "MITK Pointset (*.mps)" ); if ( aFilename.isEmpty() ) return; try { // instantiate the writer and add the point-sets to write mitk::PointSetWriter::Pointer writer = mitk::PointSetWriter::New(); writer->SetInput( dynamic_cast(m_PointSetNode->GetData()) ); writer->SetFileName( aFilename.toLatin1() ); writer->Update(); } catch(...) { QMessageBox::warning( this, "Save point set", QString("File writer reported problems writing %1\n\n" "PLEASE CHECK output file!").arg(aFilename) ); } } void QmitkPointListWidget::OnBtnLoadPoints() { // get the name of the file to load QString filename = QFileDialog::getOpenFileName( NULL, "Open MITK Pointset", "", "MITK Point Sets (*.mps)"); if ( filename.isEmpty() ) return; // attempt to load file try { mitk::PointSetReader::Pointer reader = mitk::PointSetReader::New(); reader->SetFileName( filename.toLatin1() ); reader->Update(); mitk::PointSet::Pointer pointSet = reader->GetOutput(); if ( pointSet.IsNull() ) { QMessageBox::warning( this, "Load point set", QString("File reader could not read %1").arg(filename) ); return; } // loading successful // bool interactionOn( m_Interactor.IsNotNull() ); // if (interactionOn) // { // OnEditPointSetButtonToggled(false); // } // this->SetPointSet(pointSet); // if (interactionOn) // { // OnEditPointSetButtonToggled(true); // } } catch(...) { QMessageBox::warning( this, "Load point set", QString("File reader collapsed while reading %1").arg(filename) ); } emit PointListChanged(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } mitk::PointSet* QmitkPointListWidget::GetPointSet() { return dynamic_cast(m_PointSetNode->GetData()); } mitk::DataNode* QmitkPointListWidget::GetPointSetNode() { return m_PointSetNode; } void QmitkPointListWidget::SetMultiWidget(QmitkStdMultiWidget *multiWidget) { this->m_MultiWidget = multiWidget; m_PointListView->SetMultiWidget(multiWidget); } void QmitkPointListWidget::RemoveSelectedPoint() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->RemoveSelectedPoint(); emit PointListChanged(); } void QmitkPointListWidget::MoveSelectedPointDown() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->MoveSelectedPointDown(); emit PointListChanged(); } void QmitkPointListWidget::MoveSelectedPointUp() { if (!m_PointSetNode) return; mitk::PointSet* pointSet = dynamic_cast( m_PointSetNode->GetData() ); if (!pointSet) return; if (pointSet->GetSize() == 0) return; QmitkPointListModel* pointListModel = dynamic_cast( m_PointListView->model() ); pointListModel->MoveSelectedPointUp(); emit PointListChanged(); } void QmitkPointListWidget::OnBtnAddPoint(bool checked) { if (m_PointSetNode) { if (checked) { m_Interactor = dynamic_cast(m_PointSetNode->GetInteractor()); if (m_Interactor.IsNull())//if not present, instanciate one m_Interactor = mitk::PointSetInteractor::New("pointsetinteractor", m_PointSetNode); //add it to global interaction to activate it mitk::GlobalInteraction::GetInstance()->AddInteractor( m_Interactor ); } else if ( m_Interactor ) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; } emit EditPointSets(checked); } } void QmitkPointListWidget::OnBtnAddPointManually() { mitk::PointSet* pointSet = this->GetPointSet(); int currentPosition = pointSet->GetSize(); QmitkEditPointDialog editPointDialog(this); editPointDialog.SetPoint(pointSet, currentPosition, m_TimeStep); editPointDialog.exec(); } void QmitkPointListWidget::OnListDoubleClick() { ; } void QmitkPointListWidget::OnPointSelectionChanged() { emit this->PointSelectionChanged(); } void QmitkPointListWidget::DeactivateInteractor(bool /*deactivate*/) { ; } void QmitkPointListWidget::EnableEditButton( bool enabled ) { m_EditAllowed = enabled; if (enabled == false) m_ToggleAddPoint->setEnabled(false); else m_ToggleAddPoint->setEnabled(true); OnBtnAddPoint(enabled); } void QmitkPointListWidget::ObserveNewNode( mitk::DataNode* node ) { // remove old observer if ( m_PointSetNode ) { if (m_Interactor) { mitk::GlobalInteraction::GetInstance()->RemoveInteractor( m_Interactor ); m_Interactor = NULL; m_ToggleAddPoint->setChecked( false ); } m_PointSetNode->RemoveObserver( m_NodeObserverTag ); m_NodeObserverTag = 0; } m_PointSetNode = node; // add new observer if necessary if ( m_PointSetNode ) { itk::ReceptorMemberCommand::Pointer command = itk::ReceptorMemberCommand::New(); command->SetCallbackFunction( this, &QmitkPointListWidget::OnNodeDeleted ); m_NodeObserverTag = m_PointSetNode->AddObserver( itk::DeleteEvent(), command ); } else { m_NodeObserverTag = 0; } if (m_EditAllowed == true) m_ToggleAddPoint->setEnabled( m_PointSetNode ); else m_ToggleAddPoint->setEnabled( false ); m_RemovePointBtn->setEnabled( m_PointSetNode ); m_LoadPointsBtn->setEnabled( m_PointSetNode ); m_SavePointsBtn->setEnabled(m_PointSetNode); m_AddPoint->setEnabled(m_PointSetNode); } void QmitkPointListWidget::OnNodeDeleted( const itk::EventObject & /*e*/ ) { if(m_PointSetNode.IsNotNull() && ! m_NodeObserverTag) m_PointSetNode->RemoveObserver( m_NodeObserverTag ); m_NodeObserverTag = 0; m_PointSetNode = NULL; m_PointListView->SetPointSetNode(NULL); m_ToggleAddPoint->setEnabled(false); m_RemovePointBtn->setEnabled( false ); m_LoadPointsBtn->setEnabled( false ); m_SavePointsBtn->setEnabled(false); m_AddPoint->setEnabled(false); } void QmitkPointListWidget::SetSnc1(mitk::SliceNavigationController* snc) { - m_Snc1 = snc; - m_PointListView->SetSnc1(snc); + if (snc == NULL) + { + m_PointListView->RemoveSliceNavigationController(m_Snc1); + } + else + { + m_PointListView->AddSliceNavigationController(snc); + } + m_Snc1 = snc; } void QmitkPointListWidget::SetSnc2(mitk::SliceNavigationController* snc) { - m_Snc2 = snc; - m_PointListView->SetSnc2(snc); + if (snc == NULL) + { + m_PointListView->RemoveSliceNavigationController(m_Snc2); + } + else + { + m_PointListView->AddSliceNavigationController(snc); + } + m_Snc2 = snc; } void QmitkPointListWidget::SetSnc3(mitk::SliceNavigationController* snc) { - m_Snc3 = snc; - m_PointListView->SetSnc3(snc); + if (snc == NULL) + { + m_PointListView->RemoveSliceNavigationController(m_Snc3); + } + else + { + m_PointListView->AddSliceNavigationController(snc); + } + m_Snc3 = snc; +} + +void QmitkPointListWidget::AddSliceNavigationController(mitk::SliceNavigationController* snc) +{ + m_PointListView->AddSliceNavigationController(snc); +} + +void QmitkPointListWidget::RemoveSliceNavigationController(mitk::SliceNavigationController* snc) +{ + m_PointListView->RemoveSliceNavigationController(snc); } void QmitkPointListWidget::UnselectEditButton() { m_ToggleAddPoint->setChecked(false); -} \ No newline at end of file +} diff --git a/Modules/QmitkExt/QmitkPointListWidget.h b/Modules/QmitkExt/QmitkPointListWidget.h index e63094a587..67ef291627 100644 --- a/Modules/QmitkExt/QmitkPointListWidget.h +++ b/Modules/QmitkExt/QmitkPointListWidget.h @@ -1,153 +1,171 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkPointListWidget_H #define QmitkPointListWidget_H #include #include #include "QmitkExtExports.h" #include #include #include #include #include #include /*! * \brief Widget for regular operations on point sets * * Displays a list of point coordinates and a couple of * buttons which * * \li enable point set interaction * \li clear all points from a set * \li load points from file * \li save points to file * * The user/application module of this widget needs to * assign a mitk::PointSet object to this widget. The user * also has to decide whether it wants to put the point set * into (a) DataStorage. This widget will not add/remove * point sets to DataStorage. * * If the render window crosshair should be moved to the * currently selected point, the widget user has to provide * a QmitkStdMultiWidget object. */ class QmitkExt_EXPORT QmitkPointListWidget : public QWidget { Q_OBJECT public: QmitkPointListWidget(QWidget *parent = 0, int orientation = 0); ~QmitkPointListWidget(); void SetupConnections(); ///@{ /** * \brief Sets the SliceNavigationController of the three 2D Renderwindows. * If they are defined, they can be used to automatically set the crosshair to the selected point + * \deprecatedSince{2013_03} Use AddSliceNavigationController and RemoveSliceNavigationController instead. */ - void SetSnc1(mitk::SliceNavigationController* snc); - void SetSnc2(mitk::SliceNavigationController* snc); - void SetSnc3(mitk::SliceNavigationController* snc); + DEPRECATED( void SetSnc1(mitk::SliceNavigationController* snc) ); + DEPRECATED( void SetSnc2(mitk::SliceNavigationController* snc) ); + DEPRECATED( void SetSnc3(mitk::SliceNavigationController* snc) ); ///@} + /** + * @brief Add a mitk::SliceNavigationController instance. + * @param snc The mitk::SliceNavigationController instance. + * + * This method adds \c snc to the set of slice navigation controllers which are + * used to navigate to the selected point. + */ + void AddSliceNavigationController(mitk::SliceNavigationController* snc); + + /** + * @brief Remove a mitk::SliceNavigationController instance. + * @param snc The mitk::SliceNavigationController instance. + * + * This method removes \c snc from the set of slice navigation controllers which are + * used to navigate to the selected point. + */ + void RemoveSliceNavigationController(mitk::SliceNavigationController* snc); /** @brief assign a point set (contained in a node of DataStorage) for observation */ void SetPointSet(mitk::PointSet* newPs); mitk::PointSet* GetPointSet(); /** @brief assign a point set (contained in a node of DataStorage) for observation */ void SetPointSetNode(mitk::DataNode* newNode); mitk::DataNode* GetPointSetNode(); /** @brief assign a QmitkStdMultiWidget for updating render window crosshair */ void SetMultiWidget(QmitkStdMultiWidget* multiWidget); /** @brief itk observer for node "delete" events */ void OnNodeDeleted( const itk::EventObject & e ); /** @brief Unselects the edit button if it is selected. */ void UnselectEditButton(); public slots: void DeactivateInteractor(bool deactivate); void EnableEditButton(bool enabled); signals: /** @brief signal to inform about the state of the EditPointSetButton, whether an interactor for setting points is active or not */ void EditPointSets(bool active); /// signal to inform that the selection of a point in the pointset has changed void PointSelectionChanged(); /// signal to inform about cleared or loaded point sets void PointListChanged(); protected slots: void OnBtnSavePoints(); void OnBtnLoadPoints(); void RemoveSelectedPoint(); void MoveSelectedPointDown(); void MoveSelectedPointUp(); void OnBtnAddPoint(bool checked); void OnBtnAddPointManually(); //void OnBtnSetPointsMode(bool checked); /*! \brief pass through signal from PointListView that point selection has changed */ void OnPointSelectionChanged(); void OnListDoubleClick(); protected: void SetupUi(); void ObserveNewNode(mitk::DataNode* node); QmitkPointListView* m_PointListView; QmitkStdMultiWidget* m_MultiWidget; mitk::DataNode::Pointer m_PointSetNode; int m_Orientation; QPushButton* m_MovePointUpBtn; QPushButton* m_MovePointDownBtn; QPushButton* m_RemovePointBtn; QPushButton* m_SavePointsBtn; QPushButton* m_LoadPointsBtn; QPushButton* m_ToggleAddPoint; QPushButton* m_AddPoint; mitk::SliceNavigationController* m_Snc1; mitk::SliceNavigationController* m_Snc2; mitk::SliceNavigationController* m_Snc3; mitk::PointSetInteractor::Pointer m_Interactor; int m_TimeStep; bool m_EditAllowed; unsigned long m_NodeObserverTag; }; #endif diff --git a/Modules/RigidRegistration/Documentation/Doxygen/Modules.dox b/Modules/RigidRegistration/Documentation/Doxygen/Modules.dox new file mode 100644 index 0000000000..9d2e9081ba --- /dev/null +++ b/Modules/RigidRegistration/Documentation/Doxygen/Modules.dox @@ -0,0 +1,20 @@ +/** + \defgroup Registration RigidRegistration + \ingroup MITKModules + + \brief A couple of classes related to registration. +*/ + +/** + \defgroup RigidRegistration Classes related to rigid registration + \ingroup Registration + + \brief A couple of classes related to rigid registration. +*/ + +/** + \defgroup PointBasedRegistration Classes related to point based registration + \ingroup Registration + + \brief A couple of classes related to point based registration. +*/ diff --git a/Modules/Segmentation/Rendering/mitkContourMapper2D.cpp b/Modules/Segmentation/Rendering/mitkContourMapper2D.cpp index 24487e999e..5419d13d24 100644 --- a/Modules/Segmentation/Rendering/mitkContourMapper2D.cpp +++ b/Modules/Segmentation/Rendering/mitkContourMapper2D.cpp @@ -1,129 +1,132 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkContourMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkContour.h" #include #include "mitkGL.h" mitk::ContourMapper2D::ContourMapper2D() { } mitk::ContourMapper2D::~ContourMapper2D() { } void mitk::ContourMapper2D::Paint(mitk::BaseRenderer * renderer) { - if(IsVisible(renderer)==false) return; + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if(!visible) return; //// @FIXME: Logik fuer update bool updateNeccesary=true; if (updateNeccesary) { mitk::Contour::Pointer input = const_cast(this->GetInput()); // ok, das ist aus GenerateData kopiert mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert(displayGeometry.IsNotNull()); //apply color and opacity read from the PropertyList - ApplyProperties(renderer); + ApplyColorAndOpacityProperties(renderer); vtkLinearTransform* transform = GetDataNode()->GetVtkTransform(); // Contour::OutputType point; Contour::BoundingBoxType::PointType point; mitk::Point3D p, projected_p; float vtkp[3]; float lineWidth = 3.0; if (dynamic_cast(this->GetDataNode()->GetProperty("Width")) != NULL) lineWidth = dynamic_cast(this->GetDataNode()->GetProperty("Width"))->GetValue(); glLineWidth(lineWidth); if (input->GetClosed()) { glBegin (GL_LINE_LOOP); } else { glBegin (GL_LINE_STRIP); } //Contour::InputType end = input->GetContourPath()->EndOfInput(); //if (end > 50000) end = 0; mitk::Contour::PointsContainerPointer points = input->GetPoints(); mitk::Contour::PointsContainerIterator pointsIt = points->Begin(); while ( pointsIt != points->End() ) { //while ( idx != end ) //{ // point = input->GetContourPath()->Evaluate(idx); point = pointsIt.Value(); itk2vtk(point, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); displayGeometry->Project(p, projected_p); bool projectmode=false; GetDataNode()->GetVisibility(projectmode, renderer, "project"); bool drawit=false; if(projectmode) drawit=true; else { Vector3D diff=p-projected_p; if(diff.GetSquaredNorm()<1.0) drawit=true; } if(drawit) { Point2D pt2d, tmp; displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); glVertex2f(pt2d[0], pt2d[1]); } pointsIt++; // idx += 1; } glEnd (); glLineWidth(1.0); } } const mitk::Contour* mitk::ContourMapper2D::GetInput(void) { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } diff --git a/Modules/Segmentation/Rendering/mitkContourMapper2D.h b/Modules/Segmentation/Rendering/mitkContourMapper2D.h index 82a336128b..66b7875c03 100644 --- a/Modules/Segmentation/Rendering/mitkContourMapper2D.h +++ b/Modules/Segmentation/Rendering/mitkContourMapper2D.h @@ -1,65 +1,65 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITK_CONTOUR_MAPPER_2D_H_ #define MITK_CONTOUR_MAPPER_2D_H_ #include "mitkCommon.h" #include "SegmentationExports.h" -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" namespace mitk { class BaseRenderer; class Contour; /** * @brief OpenGL-based mapper to display a mitk::Contour object in a 2D render window * * * @ingroup Mapper */ -class Segmentation_EXPORT ContourMapper2D : public GLMapper2D +class Segmentation_EXPORT ContourMapper2D : public GLMapper { public: - mitkClassMacro(ContourMapper2D, Mapper2D); + mitkClassMacro(ContourMapper2D, GLMapper); itkNewMacro(Self); /** * reimplemented from Baseclass */ virtual void Paint(BaseRenderer * renderer); /** * return a refernce of the rendered data object */ const Contour* GetInput(void); protected: ContourMapper2D(); virtual ~ContourMapper2D(); }; } // namespace mitk #endif /* MITKContourMapper2D_H_HEADER_INCLUDED */ diff --git a/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.cpp b/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.cpp index 4fbc1d95c0..4cf207e539 100644 --- a/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.cpp +++ b/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.cpp @@ -1,274 +1,277 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkContourModelGLMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkProperties.h" #include "mitkContourModel.h" #include "mitkContourModelSubDivisionFilter.h" #include #include "mitkGL.h" mitk::ContourModelGLMapper2D::ContourModelGLMapper2D() { } mitk::ContourModelGLMapper2D::~ContourModelGLMapper2D() { } void mitk::ContourModelGLMapper2D::Paint(mitk::BaseRenderer * renderer) { - if(IsVisible(renderer)==false) return; + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible ) return; bool updateNeccesary=true; int timestep = renderer->GetTimeStep(); mitk::ContourModel::Pointer input = const_cast(this->GetInput()); mitk::ContourModel::Pointer renderingContour = input; bool subdivision = false; this->GetDataNode()->GetBoolProperty( "subdivision curve", subdivision, renderer ); if (subdivision) { mitk::ContourModel::Pointer subdivContour = mitk::ContourModel::New(); mitk::ContourModelSubDivisionFilter::Pointer subdivFilter = mitk::ContourModelSubDivisionFilter::New(); subdivFilter->SetInput(input); subdivFilter->Update(); subdivContour = subdivFilter->GetOutput(); if(subdivContour->GetNumberOfVertices() == 0 ) { subdivContour = input; } renderingContour = subdivContour; } renderingContour->UpdateOutputInformation(); if( renderingContour->GetMTime() < this->m_LastUpdateTime ) updateNeccesary = false; if(renderingContour->GetNumberOfVertices(timestep) < 1) updateNeccesary = false; if (updateNeccesary) { // ok, das ist aus GenerateData kopiert mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert(displayGeometry.IsNotNull()); //apply color and opacity read from the PropertyList ApplyProperties(renderer); mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty("contour.color", renderer)); if(colorprop) { //set the color of the contour double red = colorprop->GetColor().GetRed(); double green = colorprop->GetColor().GetGreen(); double blue = colorprop->GetColor().GetBlue(); glColor4f(red,green,blue,0.5); } mitk::ColorProperty::Pointer selectedcolor = dynamic_cast(GetDataNode()->GetProperty("points.color", renderer)); if(!selectedcolor) { selectedcolor = mitk::ColorProperty::New(1.0,0.0,0.1); } vtkLinearTransform* transform = GetDataNode()->GetVtkTransform(); // ContourModel::OutputType point; mitk::Point3D point; mitk::Point3D p, projected_p; float vtkp[3]; float lineWidth = 3.0; if (dynamic_cast(this->GetDataNode()->GetProperty("contour.width")) != NULL) lineWidth = dynamic_cast(this->GetDataNode()->GetProperty("contour.width"))->GetValue(); glLineWidth(lineWidth); bool drawit=false; mitk::ContourModel::VertexIterator pointsIt = renderingContour->IteratorBegin(timestep); Point2D pt2d; // projected_p in display coordinates Point2D lastPt2d; while ( pointsIt != renderingContour->IteratorEnd(timestep) ) { lastPt2d = pt2d; point = (*pointsIt)->Coordinates; itk2vtk(point, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); Vector3D diff=p-projected_p; ScalarType scalardiff = diff.GetSquaredNorm(); //draw lines bool projectmode=false; GetDataNode()->GetVisibility(projectmode, renderer, "project"); if(projectmode) drawit=true; else { if(diff.GetSquaredNorm()<0.5) drawit=true; } if(drawit) { //lastPt2d is not valid in first step if( !(pointsIt == renderingContour->IteratorBegin(timestep)) ) { glBegin (GL_LINES); glVertex2f(pt2d[0], pt2d[1]); glVertex2f(lastPt2d[0], lastPt2d[1]); glEnd(); } //draw active points if ((*pointsIt)->IsControlPoint) { float pointsize = 4; Point2D tmp; Vector2D horz,vert; horz[0]=pointsize-scalardiff*2; horz[1]=0; vert[0]=0; vert[1]=pointsize-scalardiff*2; horz[0]=pointsize; vert[1]=pointsize; glColor3f(selectedcolor->GetColor().GetRed(), selectedcolor->GetColor().GetBlue(), selectedcolor->GetColor().GetGreen()); glLineWidth(1); //a rectangle around the point with the selected color glBegin (GL_LINE_LOOP); tmp=pt2d-horz; glVertex2fv(&tmp[0]); tmp=pt2d+vert; glVertex2fv(&tmp[0]); tmp=pt2d+horz; glVertex2fv(&tmp[0]); tmp=pt2d-vert; glVertex2fv(&tmp[0]); glEnd (); glLineWidth(1); //the actual point in the specified color to see the usual color of the point glColor3f(colorprop->GetColor().GetRed(),colorprop->GetColor().GetGreen(),colorprop->GetColor().GetBlue()); glPointSize(1); glBegin (GL_POINTS); tmp=pt2d; glVertex2fv(&tmp[0]); glEnd (); } } pointsIt++; }//end while iterate over controlpoints //close contour if necessary if(renderingContour->IsClosed(timestep) && drawit) { lastPt2d = pt2d; point = renderingContour->GetVertexAt(0,timestep)->Coordinates; itk2vtk(point, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); glBegin (GL_LINES); glVertex2f(lastPt2d[0], lastPt2d[1]); glVertex2f( pt2d[0], pt2d[1] ); glEnd(); } //draw selected vertex if exists if(renderingContour->GetSelectedVertex()) { //transform selected vertex point = renderingContour->GetSelectedVertex()->Coordinates; itk2vtk(point, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); displayGeometry->Project(p, projected_p); displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); Vector3D diff=p-projected_p; ScalarType scalardiff = diff.GetSquaredNorm(); //---------------------------------- //draw point if close to plane if(scalardiff<0.5) { float pointsize = 3.2; Point2D tmp; glColor3f(0.0, 1.0, 0.0); glLineWidth(1); //a diamond around the point glBegin (GL_LINE_LOOP); //begin from upper left corner and paint clockwise tmp[0]=pt2d[0]-pointsize; tmp[1]=pt2d[1]+pointsize; glVertex2fv(&tmp[0]); tmp[0]=pt2d[0]+pointsize; tmp[1]=pt2d[1]+pointsize; glVertex2fv(&tmp[0]); tmp[0]=pt2d[0]+pointsize; tmp[1]=pt2d[1]-pointsize; glVertex2fv(&tmp[0]); tmp[0]=pt2d[0]-pointsize; tmp[1]=pt2d[1]-pointsize; glVertex2fv(&tmp[0]); glEnd (); } //------------------------------------ } } } const mitk::ContourModel* mitk::ContourModelGLMapper2D::GetInput(void) { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } void mitk::ContourModelGLMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "contour.color", ColorProperty::New(0.9, 1.0, 0.1), renderer, overwrite ); node->AddProperty( "points.color", ColorProperty::New(1.0, 0.0, 0.1), renderer, overwrite ); node->AddProperty( "contour.width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); node->AddProperty( "subdivision curve", mitk::BoolProperty::New( false ), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.h b/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.h index dfd5e85a1c..1dc114ab1d 100644 --- a/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.h +++ b/Modules/Segmentation/Rendering/mitkContourModelGLMapper2D.h @@ -1,67 +1,67 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITK_ContourModelGLMapper2D_H_ #define MITK_ContourModelGLMapper2D_H_ #include "mitkCommon.h" #include "SegmentationExports.h" -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" namespace mitk { class BaseRenderer; class ContourModel; /** * @brief OpenGL-based mapper to display a mitk::Contour object in a 2D render window * * * @ingroup Mapper */ -class Segmentation_EXPORT ContourModelGLMapper2D : public GLMapper2D +class Segmentation_EXPORT ContourModelGLMapper2D : public GLMapper { public: - mitkClassMacro(ContourModelGLMapper2D, GLMapper2D); + mitkClassMacro(ContourModelGLMapper2D, GLMapper); itkNewMacro(Self); /** * reimplemented from Baseclass */ virtual void Paint(BaseRenderer * renderer); /** * return a refernce of the rendered data object */ const ContourModel* GetInput(void); static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); protected: ContourModelGLMapper2D(); virtual ~ContourModelGLMapper2D(); }; } // namespace mitk #endif diff --git a/Modules/Segmentation/Rendering/mitkContourModelMapper2D.cpp b/Modules/Segmentation/Rendering/mitkContourModelMapper2D.cpp index c21f69c6ad..cbdfcbce77 100644 --- a/Modules/Segmentation/Rendering/mitkContourModelMapper2D.cpp +++ b/Modules/Segmentation/Rendering/mitkContourModelMapper2D.cpp @@ -1,437 +1,390 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include mitk::ContourModelMapper2D::ContourModelMapper2D() { } mitk::ContourModelMapper2D::~ContourModelMapper2D() { } const mitk::ContourModel* mitk::ContourModelMapper2D::GetInput( void ) { //convient way to get the data from the dataNode - return static_cast< const mitk::ContourModel * >( this->GetData() ); + return static_cast< const mitk::ContourModel * >( GetDataNode()->GetData() ); } vtkProp* mitk::ContourModelMapper2D::GetVtkProp(mitk::BaseRenderer* renderer) { //return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Actor; } -void mitk::ContourModelMapper2D::MitkRenderOverlay(BaseRenderer* renderer) -{ - if ( this->IsVisible(renderer)==false ) - return; - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); - } -} - - - -void mitk::ContourModelMapper2D::MitkRenderOpaqueGeometry(BaseRenderer* renderer) -{ - if ( this->IsVisible( renderer )==false ) - return; - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); - } -} - - - -void mitk::ContourModelMapper2D::MitkRenderTranslucentGeometry(BaseRenderer* renderer) -{ - if ( this->IsVisible(renderer)==false ) - return; - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); - } -} - - - -void mitk::ContourModelMapper2D::MitkRenderVolumetricGeometry(BaseRenderer* renderer) -{ - if(IsVisible(renderer)==false) - return; - if ( GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); - } -} - - - void mitk::ContourModelMapper2D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { /*++ convert the contour to vtkPolyData and set it as input for our mapper ++*/ LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); - mitk::ContourModel* inputContour = static_cast< mitk::ContourModel* >( this->GetData() ); + mitk::ContourModel* inputContour = static_cast< mitk::ContourModel* >( GetDataNode()->GetData() ); unsigned int timestep = renderer->GetTimeStep(); //if there's something to be rendered if( inputContour->GetNumberOfVertices(timestep) > 0) { localStorage->m_OutlinePolyData = this->CreateVtkPolyDataFromContour(inputContour, renderer); } this->ApplyContourProperties(renderer); localStorage->m_Mapper->SetInput(localStorage->m_OutlinePolyData); } void mitk::ContourModelMapper2D::Update(mitk::BaseRenderer* renderer) { - if ( !this->IsVisible( renderer ) ) - { - return; - } + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible ) return; + //check if there is something to be rendered - mitk::ContourModel* data = static_cast< mitk::ContourModel*>( this->GetData() ); + mitk::ContourModel* data = static_cast< mitk::ContourModel*>( GetDataNode()->GetData() ); if ( data == NULL ) { return; } // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep( renderer ); LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); // Check if time step is valid const TimeSlicedGeometry *dataTimeGeometry = data->GetTimeSlicedGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->GetTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTime( renderer->GetTimeStep() ) ) ) { //clear the rendered polydata localStorage->m_Mapper->RemoveAllInputs();//SetInput(vtkSmartPointer::New()); return; } const DataNode *node = this->GetDataNode(); data->UpdateOutputInformation(); //check if something important has changed and we need to rerender if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified? || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { this->GenerateDataForRenderer( renderer ); } // since we have checked that nothing important has changed, we can set // m_LastUpdateTime to the current time localStorage->m_LastUpdateTime.Modified(); } vtkSmartPointer mitk::ContourModelMapper2D::CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour, mitk::BaseRenderer* renderer) { unsigned int timestep = this->GetTimestep(); // Create a polydata to store everything in vtkSmartPointer resultingPolyData = vtkSmartPointer::New(); //check for the worldgeometry from the current render window mitk::PlaneGeometry* currentWorldGeometry = dynamic_cast( const_cast(renderer->GetCurrentWorldGeometry2D())); if(currentWorldGeometry) { //origin and normal of vtkPlane mitk::Point3D origin = currentWorldGeometry->GetOrigin(); mitk::Vector3D normal = currentWorldGeometry->GetNormal(); //the implicit function to slice through the polyData vtkSmartPointer plane = vtkSmartPointer::New(); plane->SetOrigin(origin[0], origin[1], origin[2]); plane->SetNormal(normal[0], normal[1], normal[2]); /* First of all convert the control points of the contourModel to vtk points * and add lines in between them */ //the points to draw vtkSmartPointer points = vtkSmartPointer::New(); //the lines to connect the points vtkSmartPointer lines = vtkSmartPointer::New(); // Create a polydata to store everything in vtkSmartPointer polyDataIn3D = vtkSmartPointer::New(); vtkSmartPointer appendPoly = vtkSmartPointer::New(); mitk::ContourModel::Pointer renderingContour = mitk::ContourModel::New(); renderingContour = inputContour; bool subdivision = false; this->GetDataNode()->GetBoolProperty( "subdivision curve", subdivision, renderer ); if (subdivision) { mitk::ContourModel::Pointer subdivContour = mitk::ContourModel::New(); mitk::ContourModelSubDivisionFilter::Pointer subdivFilter = mitk::ContourModelSubDivisionFilter::New(); subdivFilter->SetInput(inputContour); subdivFilter->Update(); subdivContour = subdivFilter->GetOutput(); if(subdivContour->GetNumberOfVertices() == 0 ) { subdivContour = inputContour; } renderingContour = subdivContour; } //iterate over all control points mitk::ContourModel::VertexIterator current = renderingContour->IteratorBegin(timestep); mitk::ContourModel::VertexIterator next = renderingContour->IteratorBegin(timestep); if(next != renderingContour->IteratorEnd(timestep)) { next++; mitk::ContourModel::VertexIterator end = renderingContour->IteratorEnd(timestep); while(next != end) { mitk::ContourModel::VertexType* currentControlPoint = *current; mitk::ContourModel::VertexType* nextControlPoint = *next; vtkIdType p1 = points->InsertNextPoint(currentControlPoint->Coordinates[0], currentControlPoint->Coordinates[1], currentControlPoint->Coordinates[2]); vtkIdType p2 = points->InsertNextPoint(nextControlPoint->Coordinates[0], nextControlPoint->Coordinates[1], nextControlPoint->Coordinates[2]); //add the line between both contorlPoints lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); if ( currentControlPoint->IsControlPoint ) { double coordinates[3]; coordinates[0] = currentControlPoint->Coordinates[0]; coordinates[1] = currentControlPoint->Coordinates[1]; coordinates[2] = currentControlPoint->Coordinates[2]; double distance = plane->DistanceToPlane(coordinates); if(distance < 0.1) { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(1.2); sphere->SetCenter(coordinates[0], coordinates[1], coordinates[2]); sphere->Update(); appendPoly->AddInput(sphere->GetOutput()); } } current++; next++; }//end while (it!=end) //check if last control point is enabled to draw it if ( (*current)->IsControlPoint ) { double coordinates[3]; coordinates[0] = (*current)->Coordinates[0]; coordinates[1] = (*current)->Coordinates[1]; coordinates[2] = (*current)->Coordinates[2]; double distance = plane->DistanceToPlane(coordinates); if(distance < 0.1) { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(1.2); sphere->SetCenter(coordinates[0], coordinates[1], coordinates[2]); sphere->Update(); appendPoly->AddInput(sphere->GetOutput()); } } /* If the contour is closed an additional line has to be created between the very first point * and the last point */ if(renderingContour->IsClosed(timestep)) { //add a line from the last to the first control point mitk::ContourModel::VertexType* firstControlPoint = *(renderingContour->IteratorBegin(timestep)); mitk::ContourModel::VertexType* lastControlPoint = *(--(renderingContour->IteratorEnd(timestep))); vtkIdType p2 = points->InsertNextPoint(lastControlPoint->Coordinates[0], lastControlPoint->Coordinates[1], lastControlPoint->Coordinates[2]); vtkIdType p1 = points->InsertNextPoint(firstControlPoint->Coordinates[0], firstControlPoint->Coordinates[1], firstControlPoint->Coordinates[2]); //add the line between both contorlPoints lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); }//end if(isClosed) // Add the points to the dataset polyDataIn3D->SetPoints(points); // Add the lines to the dataset polyDataIn3D->SetLines(lines); //cut through polyData bool useCuttingPlane = false; this->GetDataNode()->GetBoolProperty( "use cutting plane", useCuttingPlane, renderer ); if (useCuttingPlane) { //slice through the data to get a 2D representation of the (possible) 3D contour //needed because currently there is no outher solution if the contour is within the plane vtkSmartPointer tubeFilter = vtkSmartPointer::New(); tubeFilter->SetInput(polyDataIn3D); tubeFilter->SetRadius(0.05); //cuts through vtkPolyData with a given implicit function. In our case a plane vtkSmartPointer cutter = vtkSmartPointer::New(); cutter->SetCutFunction(plane); cutter->SetInputConnection(tubeFilter->GetOutputPort()); //we want the scalars of the input - so turn off generating the scalars within vtkCutter cutter->GenerateCutScalarsOff(); cutter->Update(); //set to 2D representation of the contour resultingPolyData= cutter->GetOutput(); }//end if(project contour) else { //set to 3D polyData resultingPolyData = polyDataIn3D; } }//end if (it != end) appendPoly->AddInput(resultingPolyData); appendPoly->Update(); //return contour with control points return appendPoly->GetOutput(); }else { //return empty polyData return resultingPolyData; } } void mitk::ContourModelMapper2D::ApplyContourProperties(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); float lineWidth(1.0); if (this->GetDataNode()->GetFloatProperty( "width", lineWidth, renderer )) { localStorage->m_Actor->GetProperty()->SetLineWidth(lineWidth); } mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty("color", renderer)); if(colorprop) { //set the color of the contour double red = colorprop->GetColor().GetRed(); double green = colorprop->GetColor().GetGreen(); double blue = colorprop->GetColor().GetBlue(); localStorage->m_Actor->GetProperty()->SetColor(red, green, blue); } //make sure that directional lighting isn't used for our contour localStorage->m_Actor->GetProperty()->SetAmbient(1.0); localStorage->m_Actor->GetProperty()->SetDiffuse(0.0); localStorage->m_Actor->GetProperty()->SetSpecular(0.0); } /*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/ mitk::ContourModelMapper2D::LocalStorage* mitk::ContourModelMapper2D::GetLocalStorage(mitk::BaseRenderer* renderer) { return m_LSH.GetLocalStorage(renderer); } mitk::ContourModelMapper2D::LocalStorage::LocalStorage() { m_Mapper = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); m_OutlinePolyData = vtkSmartPointer::New(); //set the mapper for the actor m_Actor->SetMapper(m_Mapper); } void mitk::ContourModelMapper2D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "color", ColorProperty::New(0.9, 1.0, 0.1), renderer, overwrite ); node->AddProperty( "width", mitk::FloatProperty::New( 1.0 ), renderer, overwrite ); node->AddProperty( "use cutting plane", mitk::BoolProperty::New( true ), renderer, overwrite ); node->AddProperty( "subdivision curve", mitk::BoolProperty::New( false ), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/Segmentation/Rendering/mitkContourModelMapper2D.h b/Modules/Segmentation/Rendering/mitkContourModelMapper2D.h index 90bb5d66f7..c0d3f9b34f 100644 --- a/Modules/Segmentation/Rendering/mitkContourModelMapper2D.h +++ b/Modules/Segmentation/Rendering/mitkContourModelMapper2D.h @@ -1,113 +1,108 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_CONTOURMODEL_MAPPER_H_ #define _MITK_CONTOURMODEL_MAPPER_H_ #include "mitkCommon.h" #include "SegmentationExports.h" #include "mitkBaseRenderer.h" -#include "mitkVtkMapper2D.h" +#include "mitkVtkMapper.h" #include "mitkContourModel.h" //#include "mitkContourModelToVtkPolyDataFilter.h" #include #include #include #include #include #include namespace mitk { - class Segmentation_EXPORT ContourModelMapper2D : public VtkMapper2D + class Segmentation_EXPORT ContourModelMapper2D : public VtkMapper { public: /** Standard class typedefs. */ - mitkClassMacro( ContourModelMapper2D,VtkMapper2D ); + mitkClassMacro( ContourModelMapper2D,VtkMapper ); /** Method for creation through the object factory. */ itkNewMacro(Self); const mitk::ContourModel* GetInput(void); /** \brief Checks whether this mapper needs to update itself and generate * data. */ virtual void Update(mitk::BaseRenderer * renderer); /*+++ methods of MITK-VTK rendering pipeline +++*/ virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); - - virtual void MitkRenderOverlay(BaseRenderer* renderer); - virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer); - virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer); - virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer); /*+++ END methods of MITK-VTK rendering pipeline +++*/ class Segmentation_EXPORT LocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Actor of a 2D render window. */ vtkSmartPointer m_Actor; /** \brief Mapper of a 2D render window. */ vtkSmartPointer m_Mapper; //mitk::ContourModelToVtkPolyDataFilter::Pointer m_contourToPolyData; vtkSmartPointer m_OutlinePolyData; /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief Default constructor of the local storage. */ LocalStorage(); /** \brief Default deconstructor of the local storage. */ ~LocalStorage() { } }; /** \brief The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows. */ mitk::Mapper::LocalStorageHandler m_LSH; /** \brief Get the LocalStorage corresponding to the current renderer. */ LocalStorage* GetLocalStorage(mitk::BaseRenderer* renderer); /** \brief Set the default properties for general image rendering. */ static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); protected: ContourModelMapper2D(); virtual ~ContourModelMapper2D(); void GenerateDataForRenderer( mitk::BaseRenderer *renderer ); virtual vtkSmartPointer CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour, mitk::BaseRenderer* renderer); virtual void ApplyContourProperties(mitk::BaseRenderer* renderer); }; } #endif diff --git a/Modules/Segmentation/Rendering/mitkContourModelMapper3D.cpp b/Modules/Segmentation/Rendering/mitkContourModelMapper3D.cpp index 3bd8662b59..45075dc3da 100644 --- a/Modules/Segmentation/Rendering/mitkContourModelMapper3D.cpp +++ b/Modules/Segmentation/Rendering/mitkContourModelMapper3D.cpp @@ -1,291 +1,242 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include mitk::ContourModelMapper3D::ContourModelMapper3D() { } mitk::ContourModelMapper3D::~ContourModelMapper3D() { } const mitk::ContourModel* mitk::ContourModelMapper3D::GetInput( void ) { //convient way to get the data from the dataNode - return static_cast< const mitk::ContourModel * >( this->GetData() ); + return static_cast< const mitk::ContourModel * >( GetDataNode()->GetData() ); } vtkProp* mitk::ContourModelMapper3D::GetVtkProp(mitk::BaseRenderer* renderer) { //return the actor corresponding to the renderer return m_LSH.GetLocalStorage(renderer)->m_Actor; } -void mitk::ContourModelMapper3D::MitkRenderOverlay(BaseRenderer* renderer) -{ - if ( this->IsVisible(renderer)==false ) - return; - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderOverlay(renderer->GetVtkRenderer()); - } -} - - - -void mitk::ContourModelMapper3D::MitkRenderOpaqueGeometry(BaseRenderer* renderer) -{ - if ( this->IsVisible( renderer )==false ) - return; - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderOpaqueGeometry( renderer->GetVtkRenderer() ); - } -} - - - -void mitk::ContourModelMapper3D::MitkRenderTranslucentGeometry(BaseRenderer* renderer) -{ - if ( this->IsVisible(renderer)==false ) - return; - if ( this->GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderTranslucentPolygonalGeometry(renderer->GetVtkRenderer()); - } -} - - - -void mitk::ContourModelMapper3D::MitkRenderVolumetricGeometry(BaseRenderer* renderer) -{ - if(IsVisible(renderer)==false) - return; - if ( GetVtkProp(renderer)->GetVisibility() ) - { - this->GetVtkProp(renderer)->RenderVolumetricGeometry(renderer->GetVtkRenderer()); - } -} - - - void mitk::ContourModelMapper3D::GenerateDataForRenderer( mitk::BaseRenderer *renderer ) { /* First convert the contourModel to vtkPolyData, then tube filter it and * set it input for our mapper */ LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); - mitk::ContourModel* inputContour = static_cast< mitk::ContourModel* >( this->GetData() ); + mitk::ContourModel* inputContour = static_cast< mitk::ContourModel* >( GetDataNode()->GetData() ); localStorage->m_OutlinePolyData = this->CreateVtkPolyDataFromContour(inputContour); this->ApplyContourProperties(renderer); //tube filter the polyData localStorage->m_TubeFilter->SetInput(localStorage->m_OutlinePolyData); float lineWidth(1.0); if (this->GetDataNode()->GetFloatProperty( "3D contour width", lineWidth, renderer )) { localStorage->m_TubeFilter->SetRadius(lineWidth); }else { localStorage->m_TubeFilter->SetRadius(0.2); } localStorage->m_TubeFilter->CappingOn(); localStorage->m_TubeFilter->SetNumberOfSides(10); localStorage->m_TubeFilter->Update(); localStorage->m_Mapper->SetInput(localStorage->m_TubeFilter->GetOutput()); } void mitk::ContourModelMapper3D::Update(mitk::BaseRenderer* renderer) { - if ( !this->IsVisible( renderer ) ) - { - return; - } + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + - mitk::ContourModel* data = static_cast< mitk::ContourModel*>( this->GetData() ); + mitk::ContourModel* data = static_cast< mitk::ContourModel*>( GetDataNode()->GetData() ); if ( data == NULL ) { return; } // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep( renderer ); LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); // Check if time step is valid const TimeSlicedGeometry *dataTimeGeometry = data->GetTimeSlicedGeometry(); if ( ( dataTimeGeometry == NULL ) || ( dataTimeGeometry->GetTimeSteps() == 0 ) || ( !dataTimeGeometry->IsValidTime( renderer->GetTimeStep() ) ) ) { //clear the rendered polydata localStorage->m_Mapper->SetInput(vtkSmartPointer::New()); return; } const DataNode *node = this->GetDataNode(); data->UpdateOutputInformation(); //check if something important has changed and we need to rerender if ( (localStorage->m_LastUpdateTime < node->GetMTime()) //was the node modified? || (localStorage->m_LastUpdateTime < data->GetPipelineMTime()) //Was the data modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2DUpdateTime()) //was the geometry modified? || (localStorage->m_LastUpdateTime < renderer->GetCurrentWorldGeometry2D()->GetMTime()) || (localStorage->m_LastUpdateTime < node->GetPropertyList()->GetMTime()) //was a property modified? || (localStorage->m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime()) ) { this->GenerateDataForRenderer( renderer ); } // since we have checked that nothing important has changed, we can set // m_LastUpdateTime to the current time localStorage->m_LastUpdateTime.Modified(); } vtkSmartPointer mitk::ContourModelMapper3D::CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour) { unsigned int timestep = this->GetTimestep(); //the points to draw vtkSmartPointer points = vtkSmartPointer::New(); //the lines to connect the points vtkSmartPointer lines = vtkSmartPointer::New(); // Create a polydata to store everything in vtkSmartPointer polyData = vtkSmartPointer::New(); //iterate over the control points mitk::ContourModel::VertexIterator current = inputContour->IteratorBegin(timestep); mitk::ContourModel::VertexIterator next = inputContour->IteratorBegin(timestep); if(next != inputContour->IteratorEnd(timestep)) { next++; mitk::ContourModel::VertexIterator end = inputContour->IteratorEnd(timestep); while(next != end) { mitk::ContourModel::VertexType* currentControlPoint = *current; mitk::ContourModel::VertexType* nextControlPoint = *next; if( !(currentControlPoint->Coordinates[0] == nextControlPoint->Coordinates[0] && currentControlPoint->Coordinates[1] == nextControlPoint->Coordinates[1] && currentControlPoint->Coordinates[2] == nextControlPoint->Coordinates[2])) { vtkIdType p1 = points->InsertNextPoint(currentControlPoint->Coordinates[0], currentControlPoint->Coordinates[1], currentControlPoint->Coordinates[2]); vtkIdType p2 = points->InsertNextPoint(nextControlPoint->Coordinates[0], nextControlPoint->Coordinates[1], nextControlPoint->Coordinates[2]); //add the line between both contorlPoints lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } current++; next++; } if(inputContour->IsClosed(timestep)) { // If the contour is closed add a line from the last to the first control point mitk::ContourModel::VertexType* firstControlPoint = *(inputContour->IteratorBegin(timestep)); mitk::ContourModel::VertexType* lastControlPoint = *(--(inputContour->IteratorEnd(timestep))); if( lastControlPoint->Coordinates[0] != firstControlPoint->Coordinates[0] && lastControlPoint->Coordinates[1] != firstControlPoint->Coordinates[1] && lastControlPoint->Coordinates[2] != firstControlPoint->Coordinates[2]) { vtkIdType p2 = points->InsertNextPoint(lastControlPoint->Coordinates[0], lastControlPoint->Coordinates[1], lastControlPoint->Coordinates[2]); vtkIdType p1 = points->InsertNextPoint(firstControlPoint->Coordinates[0], firstControlPoint->Coordinates[1], firstControlPoint->Coordinates[2]); //add the line to the cellArray lines->InsertNextCell(2); lines->InsertCellPoint(p1); lines->InsertCellPoint(p2); } } // Add the points to the dataset polyData->SetPoints(points); // Add the lines to the dataset polyData->SetLines(lines); } return polyData; } void mitk::ContourModelMapper3D::ApplyContourProperties(mitk::BaseRenderer* renderer) { LocalStorage *localStorage = m_LSH.GetLocalStorage(renderer); mitk::ColorProperty::Pointer colorprop = dynamic_cast(GetDataNode()->GetProperty ("color", renderer)); if(colorprop) { //set the color of the contour double red = colorprop->GetColor().GetRed(); double green = colorprop->GetColor().GetGreen(); double blue = colorprop->GetColor().GetBlue(); localStorage->m_Actor->GetProperty()->SetColor(red, green, blue); } } /*+++++++++++++++++++ LocalStorage part +++++++++++++++++++++++++*/ mitk::ContourModelMapper3D::LocalStorage* mitk::ContourModelMapper3D::GetLocalStorage(mitk::BaseRenderer* renderer) { return m_LSH.GetLocalStorage(renderer); } mitk::ContourModelMapper3D::LocalStorage::LocalStorage() { m_Mapper = vtkSmartPointer::New(); m_Actor = vtkSmartPointer::New(); m_OutlinePolyData = vtkSmartPointer::New(); m_TubeFilter = vtkSmartPointer::New(); //set the mapper for the actor m_Actor->SetMapper(m_Mapper); } void mitk::ContourModelMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "color", ColorProperty::New(1.0,0.0,0.0), renderer, overwrite ); node->AddProperty( "3D contour width", mitk::FloatProperty::New( 0.2 ), renderer, overwrite ); Superclass::SetDefaultProperties(node, renderer, overwrite); } diff --git a/Modules/Segmentation/Rendering/mitkContourModelMapper3D.h b/Modules/Segmentation/Rendering/mitkContourModelMapper3D.h index 3bf54bf5d3..a14f65f0ff 100644 --- a/Modules/Segmentation/Rendering/mitkContourModelMapper3D.h +++ b/Modules/Segmentation/Rendering/mitkContourModelMapper3D.h @@ -1,114 +1,110 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_CONTOURMODEL_MAPPER_3D_H_ #define _MITK_CONTOURMODEL_MAPPER_3D_H_ #include "mitkCommon.h" #include "SegmentationExports.h" #include "mitkBaseRenderer.h" -#include "mitkVtkMapper2D.h" +#include "mitkVtkMapper.h" #include "mitkContourModel.h" //#include "mitkContourModelToVtkPolyDataFilter.h" #include #include #include #include #include #include namespace mitk { - class Segmentation_EXPORT ContourModelMapper3D : public VtkMapper2D + class Segmentation_EXPORT ContourModelMapper3D : public VtkMapper { public: /** Standard class typedefs. */ - mitkClassMacro( ContourModelMapper3D,VtkMapper2D ); + mitkClassMacro( ContourModelMapper3D,VtkMapper ); /** Method for creation through the object factory. */ itkNewMacro(Self); const mitk::ContourModel* GetInput(void); /** \brief Checks whether this mapper needs to update itself and generate * data. */ virtual void Update(mitk::BaseRenderer * renderer); /*+++ methods of MITK-VTK rendering pipeline +++*/ virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); - virtual void MitkRenderOverlay(BaseRenderer* renderer); - virtual void MitkRenderOpaqueGeometry(BaseRenderer* renderer); - virtual void MitkRenderTranslucentGeometry(BaseRenderer* renderer); - virtual void MitkRenderVolumetricGeometry(BaseRenderer* renderer); /*+++ END methods of MITK-VTK rendering pipeline +++*/ class Segmentation_EXPORT LocalStorage : public mitk::Mapper::BaseLocalStorage { public: /** \brief Actor of a 2D render window. */ vtkSmartPointer m_Actor; /** \brief Mapper of a 2D render window. */ vtkSmartPointer m_Mapper; vtkSmartPointer m_TubeFilter; //mitk::ContourModelToVtkPolyDataFilter::Pointer m_contourToPolyData; vtkSmartPointer m_OutlinePolyData; /** \brief Timestamp of last update of stored data. */ itk::TimeStamp m_LastUpdateTime; /** \brief Default constructor of the local storage. */ LocalStorage(); /** \brief Default deconstructor of the local storage. */ ~LocalStorage() { } }; /** \brief The LocalStorageHandler holds all (three) LocalStorages for the three 2D render windows. */ mitk::Mapper::LocalStorageHandler m_LSH; /** \brief Get the LocalStorage corresponding to the current renderer. */ LocalStorage* GetLocalStorage(mitk::BaseRenderer* renderer); /** \brief Set the default properties for general image rendering. */ static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); protected: ContourModelMapper3D(); virtual ~ContourModelMapper3D(); void GenerateDataForRenderer( mitk::BaseRenderer *renderer ); virtual vtkSmartPointer CreateVtkPolyDataFromContour(mitk::ContourModel* inputContour); virtual void ApplyContourProperties(mitk::BaseRenderer* renderer); }; } #endif diff --git a/Modules/Segmentation/Rendering/mitkContourSetMapper2D.cpp b/Modules/Segmentation/Rendering/mitkContourSetMapper2D.cpp index 176fed49af..5d6b7abe3d 100644 --- a/Modules/Segmentation/Rendering/mitkContourSetMapper2D.cpp +++ b/Modules/Segmentation/Rendering/mitkContourSetMapper2D.cpp @@ -1,127 +1,130 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkContourSetMapper2D.h" #include "mitkBaseRenderer.h" #include "mitkPlaneGeometry.h" #include "mitkColorProperty.h" #include "mitkContourSet.h" #include "mitkProperties.h" #include #include "mitkGL.h" mitk::ContourSetMapper2D::ContourSetMapper2D() { } mitk::ContourSetMapper2D::~ContourSetMapper2D() { } void mitk::ContourSetMapper2D::Paint(mitk::BaseRenderer * renderer) { - if(IsVisible(renderer)==false) return; + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if(!visible) return; //// @FIXME: Logik fuer update bool updateNeccesary=true; if (updateNeccesary) { // ok, das ist aus GenerateData kopiert mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry(); assert(displayGeometry.IsNotNull()); //apply color and opacity read from the PropertyList - ApplyProperties(renderer); + ApplyColorAndOpacityProperties(renderer); mitk::ContourSet::Pointer input = const_cast(this->GetInput()); mitk::ContourSet::ContourVectorType contourVec = input->GetContours(); mitk::ContourSet::ContourIterator contourIt = contourVec.begin(); while ( contourIt != contourVec.end() ) { mitk::Contour::Pointer nextContour = (mitk::Contour::Pointer) (*contourIt).second; vtkLinearTransform* transform = GetDataNode()->GetVtkTransform(); // Contour::OutputType point; Contour::BoundingBoxType::PointType point; mitk::Point3D p, projected_p; float vtkp[3]; glLineWidth( nextContour->GetWidth() ); if (nextContour->GetClosed()) { glBegin (GL_LINE_LOOP); } else { glBegin (GL_LINE_STRIP); } //float rgba[4]={1.0f,1.0f,1.0f,1.0f}; //if ( nextContour->GetSelected() ) //{ // rgba[0] = 1.0; // rgba[1] = 0.0; // rgba[2] = 0.0; //} //glColor4fv(rgba); mitk::Contour::PointsContainerPointer points = nextContour->GetPoints(); mitk::Contour::PointsContainerIterator pointsIt = points->Begin(); while ( pointsIt != points->End() ) { point = pointsIt.Value(); itk2vtk(point, vtkp); transform->TransformPoint(vtkp, vtkp); vtk2itk(vtkp,p); displayGeometry->Project(p, projected_p); Vector3D diff=p-projected_p; if(diff.GetSquaredNorm()<1.0) { Point2D pt2d, tmp; displayGeometry->Map(projected_p, pt2d); displayGeometry->WorldToDisplay(pt2d, pt2d); glVertex2f(pt2d[0], pt2d[1]); } pointsIt++; // idx += 1; } glEnd (); glLineWidth(1.0); contourIt++; } } } const mitk::ContourSet* mitk::ContourSetMapper2D::GetInput(void) { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } diff --git a/Modules/Segmentation/Rendering/mitkContourSetMapper2D.h b/Modules/Segmentation/Rendering/mitkContourSetMapper2D.h index ddb0b571da..4088433bee 100644 --- a/Modules/Segmentation/Rendering/mitkContourSetMapper2D.h +++ b/Modules/Segmentation/Rendering/mitkContourSetMapper2D.h @@ -1,65 +1,64 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITK_CONTOUR_SET_MAPPER_2D_H_ #define MITK_CONTOUR_SET_MAPPER_2D_H_ #include "mitkCommon.h" #include "SegmentationExports.h" -#include "mitkGLMapper2D.h" +#include "mitkGLMapper.h" namespace mitk { class BaseRenderer; class ContourSet; -class BaseRenderer; /** * @brief OpenGL-based mapper to display a mitk::Contour object in a 2D render window * * * @ingroup Mapper */ -class Segmentation_EXPORT ContourSetMapper2D : public GLMapper2D +class Segmentation_EXPORT ContourSetMapper2D : public GLMapper { public: - mitkClassMacro(ContourSetMapper2D, Mapper2D); + mitkClassMacro(ContourSetMapper2D, GLMapper); itkNewMacro(Self); /** * reimplemented from Baseclass */ virtual void Paint(mitk::BaseRenderer * renderer); /** * return a refernce of the rendered data object */ const mitk::ContourSet * GetInput(void); protected: ContourSetMapper2D(); virtual ~ContourSetMapper2D(); }; } // namespace mitk #endif /* MITK_CONTOUR_SET_MAPPER_2D_H_ */ diff --git a/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.cpp b/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.cpp index e618b7e8e8..df216bafa7 100644 --- a/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.cpp +++ b/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.cpp @@ -1,162 +1,166 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkContourSetVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkColorProperty.h" #include "mitkVtkPropRenderer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include mitk::ContourSetVtkMapper3D::ContourSetVtkMapper3D() { m_VtkPolyDataMapper = vtkPolyDataMapper::New(); m_Actor = vtkActor::New(); m_Actor->SetMapper(m_VtkPolyDataMapper); m_ContourSet = vtkPolyData::New(); m_TubeFilter = vtkTubeFilter::New(); } mitk::ContourSetVtkMapper3D::~ContourSetVtkMapper3D() { if( m_VtkPolyDataMapper ) m_VtkPolyDataMapper->Delete();; if( m_TubeFilter ) m_TubeFilter->Delete();; if( m_ContourSet ) m_ContourSet->Delete();; if( m_Actor ) m_Actor->Delete();; } vtkProp* mitk::ContourSetVtkMapper3D::GetVtkProp(mitk::BaseRenderer* /*renderer*/) { return m_Actor; } void mitk::ContourSetVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) { - if(IsVisible(renderer)==false) + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if(!visible) { m_Actor->VisibilityOff(); return; } + m_Actor->VisibilityOn(); mitk::ContourSet::Pointer input = const_cast(this->GetInput()); if ( renderer->GetDisplayGeometryUpdateTime() > this->GetInput()->GetMTime() ) { m_ContourSet = vtkPolyData::New(); vtkPoints *points = vtkPoints::New(); vtkCellArray *lines = vtkCellArray::New(); mitk::ContourSet::Pointer input = const_cast(this->GetInput()); mitk::ContourSet::ContourVectorType contourVec = input->GetContours(); mitk::ContourSet::ContourIterator contourIt = contourVec.begin(); vtkIdType firstPointIndex= 0, lastPointIndex=0; vtkIdType ptIndex = 0; while ( contourIt != contourVec.end() ) { mitk::Contour* nextContour = (mitk::Contour*) (*contourIt).second; Contour::InputType idx = nextContour->GetContourPath()->StartOfInput(); Contour::InputType end = nextContour->GetContourPath()->EndOfInput(); if (end > 50000) end = 0; mitk::Contour::PointsContainerPointer contourPoints = nextContour->GetPoints(); mitk::Contour::PointsContainerIterator pointsIt = contourPoints->Begin(); unsigned int counter = 0; firstPointIndex=ptIndex; while ( pointsIt != contourPoints->End() ) { if (counter %2 == 0) { Contour::BoundingBoxType::PointType point; point = pointsIt.Value(); points->InsertPoint(ptIndex, point[0],point[1],point[2]); if (ptIndex > firstPointIndex) { int cell[2] = {ptIndex-1,ptIndex}; lines->InsertNextCell((vtkIdType)2,(vtkIdType*) cell); } lastPointIndex=ptIndex; ptIndex++; } pointsIt++; idx+=1; } if (nextContour->GetClosed()) { int cell[2] = {lastPointIndex,firstPointIndex}; lines->InsertNextCell((vtkIdType)2,(vtkIdType*) cell); } contourIt++; } m_ContourSet->SetPoints(points); m_ContourSet->SetLines(lines); m_ContourSet->Update(); m_TubeFilter->SetInput(m_ContourSet); m_TubeFilter->SetRadius(1); m_TubeFilter->Update(); m_VtkPolyDataMapper->SetInput(m_TubeFilter->GetOutput()); vtkFloatingPointType rgba[4]={0.0f,1.0f,0.0f,0.6f}; m_Actor->GetProperty()->SetColor(rgba); m_Actor->SetMapper(m_VtkPolyDataMapper); } SetVtkMapperImmediateModeRendering(m_VtkPolyDataMapper); } const mitk::ContourSet* mitk::ContourSetVtkMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } diff --git a/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.h b/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.h index 67b0c7993f..7d83a0ea07 100644 --- a/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.h +++ b/Modules/Segmentation/Rendering/mitkContourSetVtkMapper3D.h @@ -1,69 +1,69 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITK_CONTOUR_SET_VTK_MAPPER_3D_H #define MITK_CONTOUR_SET_VTK_MAPPER_3D_H #include "mitkCommon.h" #include "SegmentationExports.h" -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include "mitkContourSet.h" #include "mitkBaseRenderer.h" #include class vtkPolyDataMapper; class vtkAppendPolyData; class vtkActor; class vtkTubeFilter; namespace mitk { //##Documentation //## @brief Vtk-based mapper for mitk::Contour //## @ingroup Mapper -class Segmentation_EXPORT ContourSetVtkMapper3D : public VtkMapper3D +class Segmentation_EXPORT ContourSetVtkMapper3D : public VtkMapper { public: - mitkClassMacro(ContourSetVtkMapper3D, VtkMapper3D); + mitkClassMacro(ContourSetVtkMapper3D, VtkMapper); itkNewMacro(Self); virtual const mitk::ContourSet* GetInput(); virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); protected: ContourSetVtkMapper3D(); virtual ~ContourSetVtkMapper3D(); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); vtkPolyDataMapper* m_VtkPolyDataMapper; vtkTubeFilter* m_TubeFilter; vtkPolyData *m_ContourSet; vtkActor *m_Actor; }; } // namespace mitk #endif // MITK_CONTOUR_VTK_MAPPER_3D_H diff --git a/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.cpp b/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.cpp index 482b8be4b5..4a4c5be811 100644 --- a/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.cpp +++ b/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.cpp @@ -1,180 +1,183 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkContourVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkColorProperty.h" #include "mitkVtkPropRenderer.h" #include "mitkContour.h" #include #include #include #pragma GCC diagnostic ignored "-Wstrict-aliasing" #include #pragma GCC diagnostic warning "-Wstrict-aliasing" #include #include #include #include #include #include #include #include #include #include mitk::ContourVtkMapper3D::ContourVtkMapper3D() { m_VtkPolyDataMapper = vtkPolyDataMapper::New(); m_VtkPointList = vtkAppendPolyData::New(); m_Actor = vtkActor::New(); m_Actor->SetMapper(m_VtkPolyDataMapper); m_TubeFilter = vtkTubeFilter::New(); } mitk::ContourVtkMapper3D::~ContourVtkMapper3D() { if(m_VtkPolyDataMapper) m_VtkPolyDataMapper->Delete(); if(m_TubeFilter) m_TubeFilter->Delete(); if(m_VtkPointList) m_VtkPointList->Delete(); if(m_Contour) m_Contour->Delete(); if(m_Actor) m_Actor->Delete(); } vtkProp* mitk::ContourVtkMapper3D::GetVtkProp(mitk::BaseRenderer* /*renderer*/) { return m_Actor; } void mitk::ContourVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) { - if ( IsVisible(renderer)==false ) + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); + + if ( !visible ) { m_Actor->VisibilityOff(); return; } m_Actor->VisibilityOn(); m_Contour = vtkPolyData::New(); mitk::Contour::Pointer input = const_cast(this->GetInput()); bool makeContour = true; if ( makeContour ) { vtkSmartPointer points = vtkSmartPointer::New(); vtkSmartPointer lines = vtkSmartPointer::New(); int numPts=input->GetNumberOfPoints(); if ( numPts > 200000 ) numPts = 200000; mitk::Contour::PathPointer path = input->GetContourPath(); mitk::Contour::PathType::InputType cstart = path->StartOfInput(); mitk::Contour::PathType::InputType cend = path->EndOfInput(); mitk::Contour::PathType::InputType cstep = (cend-cstart+1)/numPts; mitk::Contour::PathType::InputType ccur; vtkIdType ptIndex = 0; vtkIdType lastPointIndex = 0; mitk::Contour::PointsContainerPointer contourPoints = input->GetPoints(); mitk::Contour::PointsContainerIterator pointsIt = contourPoints->Begin(); vtkFloatingPointType vtkpoint[3]; int i; float pointSize = 2; this->GetDataNode()->GetFloatProperty("spheres size", pointSize); bool showPoints = true; this->GetDataNode()->GetBoolProperty("show points", showPoints); if ( showPoints ) { m_VtkPointList = vtkAppendPolyData::New(); } for ( i=0, ccur=cstart; iEvaluate(ccur), vtkpoint); points->InsertPoint(ptIndex, vtkpoint); if ( ptIndex > 0 ) { int cell[2] = {ptIndex-1,ptIndex}; lines->InsertNextCell((vtkIdType)2,(vtkIdType*) cell); } lastPointIndex = ptIndex; ++ptIndex; if ( showPoints ) { vtkSmartPointer sphere = vtkSmartPointer::New(); sphere->SetRadius(pointSize); sphere->SetCenter(vtkpoint); m_VtkPointList->AddInput(sphere->GetOutput()); sphere->Update(); } } if ( input->GetClosed() ) { int cell[2] = {lastPointIndex,0}; lines->InsertNextCell((vtkIdType)2,(vtkIdType*) cell); } m_Contour->SetPoints(points); m_Contour->SetLines(lines); m_Contour->Update(); m_TubeFilter->SetInput(m_Contour); m_TubeFilter->SetRadius(pointSize / 2.0f); m_TubeFilter->SetNumberOfSides(8); m_TubeFilter->Update(); if ( showPoints ) { m_VtkPointList->AddInput(m_TubeFilter->GetOutput()); m_VtkPolyDataMapper->SetInput(m_VtkPointList->GetOutput()); } else { m_VtkPolyDataMapper->SetInput(m_TubeFilter->GetOutput()); } vtkFloatingPointType rgba[4]={0.0f,1.0f,0.0f,0.6f}; m_Actor->GetProperty()->SetColor(rgba); m_Actor->SetMapper(m_VtkPolyDataMapper); } SetVtkMapperImmediateModeRendering(m_VtkPolyDataMapper); } const mitk::Contour* mitk::ContourVtkMapper3D::GetInput() { - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } diff --git a/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.h b/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.h index 5e97c98651..5d14be787c 100644 --- a/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.h +++ b/Modules/Segmentation/Rendering/mitkContourVtkMapper3D.h @@ -1,68 +1,68 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITK_CONTOUR_VTK_MAPPER_3D_H #define MITK_CONTOUR_VTK_MAPPER_3D_H #include "SegmentationExports.h" -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include #include class vtkPolyDataMapper; class vtkAppendPolyData; class vtkActor; class vtkTubeFilter; namespace mitk { class BaseRenderer; class Contour; /** @brief Vtk-based mapper for mitk::Contour @ingroup Mapper */ -class Segmentation_EXPORT ContourVtkMapper3D : public VtkMapper3D +class Segmentation_EXPORT ContourVtkMapper3D : public VtkMapper { public: - mitkClassMacro(ContourVtkMapper3D, VtkMapper3D); + mitkClassMacro(ContourVtkMapper3D, VtkMapper); itkNewMacro(Self); virtual const mitk::Contour* GetInput(); virtual vtkProp* GetVtkProp(mitk::BaseRenderer* renderer); protected: ContourVtkMapper3D(); virtual ~ContourVtkMapper3D(); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); vtkSmartPointer m_VtkPolyDataMapper; vtkSmartPointer m_TubeFilter; vtkSmartPointer m_VtkPointList; vtkSmartPointer m_Contour; vtkSmartPointer m_Actor; }; } // namespace mitk #endif // MITK_CONTOUR_VTK_MAPPER_3D_H diff --git a/Modules/Segmentation/Testing/mitkDataNodeSegmentationTest.cpp b/Modules/Segmentation/Testing/mitkDataNodeSegmentationTest.cpp index ce31fb59ab..f4a654d6f6 100644 --- a/Modules/Segmentation/Testing/mitkDataNodeSegmentationTest.cpp +++ b/Modules/Segmentation/Testing/mitkDataNodeSegmentationTest.cpp @@ -1,164 +1,164 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDataNode.h" #include #include "mitkVtkPropRenderer.h" #include "mitkTestingMacros.h" #include "mitkGlobalInteraction.h" #include //Basedata Test #include #include #include //Mapper Test #include -#include -#include +#include +#include #include #include #include #include //Interactors #include #include #include //Propertylist Test #include #include #include #include #include #include #include #include #include #include #include /** * Extended test for mitk::DataNode. A number of tests from the core test * mitkDataNodeTest are assumed to pass! */ class mitkDataNodeSegmentationTestClass { public: static void TestDataSetting(mitk::DataNode::Pointer dataNode) { mitk::BaseData::Pointer baseData; //NULL pointer Test dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a NULL pointer was set correctly" ) baseData = mitk::Contour::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a Contour object was set correctly" ) baseData = mitk::ContourSet::New(); dataNode->SetData(baseData); MITK_TEST_CONDITION( baseData == dataNode->GetData(), "Testing if a ContourSet object was set correctly" ) } static void TestMapperSetting(mitk::DataNode::Pointer dataNode) { //tests the SetMapper() method //in dataNode is a mapper vector which can be accessed by index //in this test method we use only slot 0 (filled with null) and slot 1 //so we also test the destructor of the mapper classes mitk::Mapper::Pointer mapper; dataNode->SetMapper(0,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(0), "Testing if a NULL pointer was set correctly" ) mapper = mitk::ContourMapper2D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a ContourMapper2D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::ContourSetMapper2D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a ContourSetMapper2D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) //3D Mappers mapper = mitk::ContourSetVtkMapper3D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a ContourSetVtkMapper3D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) mapper = mitk::ContourVtkMapper3D::New(); dataNode->SetMapper(1,mapper); MITK_TEST_CONDITION( mapper == dataNode->GetMapper(1), "Testing if a ContourVtkMapper3D was set correctly" ) MITK_TEST_CONDITION( dataNode == mapper->GetDataNode(), "Testing if the mapper returns the right DataNode" ) } static void TestInteractorSetting(mitk::DataNode::Pointer dataNode) { //this method tests the SetInteractor() and GetInteractor methods //the Interactor base class calls the DataNode->SetInteractor method mitk::Interactor::Pointer interactor; MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a NULL pointer was set correctly (Interactor)" ) interactor = mitk::ContourInteractor::New("AffineInteractions click to select", dataNode); MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a ContourInteractor was set correctly" ) interactor = mitk::ExtrudedContourInteractor::New("AffineInteractions click to select", dataNode); MITK_TEST_CONDITION( interactor == dataNode->GetInteractor(), "Testing if a ExtrudedContourInteractor was set correctly" ) } }; int mitkDataNodeSegmentationTest(int /* argc */, char* /*argv*/[]) { // always start with this! MITK_TEST_BEGIN("DataNode") // Global interaction must(!) be initialized mitk::GlobalInteraction::GetInstance()->Initialize("global"); // let's create an object of our class mitk::DataNode::Pointer myDataNode = mitk::DataNode::New(); // first test: did this work? // using MITK_TEST_CONDITION_REQUIRED makes the test stop after failure, since // it makes no sense to continue without an object. MITK_TEST_CONDITION_REQUIRED(myDataNode.IsNotNull(),"Testing instantiation") //test setData() Method mitkDataNodeSegmentationTestClass::TestDataSetting(myDataNode); mitkDataNodeSegmentationTestClass::TestMapperSetting(myDataNode); //note, that no data is set to the dataNode mitkDataNodeSegmentationTestClass::TestInteractorSetting(myDataNode); // write your own tests here and use the macros from mitkTestingMacros.h !!! // do not write to std::cout and do not return from this function yourself! // always end with this! MITK_TEST_END() } diff --git a/Modules/Simulation/mitkSimulationDrawTool.cpp b/Modules/Simulation/mitkSimulationDrawTool.cpp index 69687e89c4..456a907ce4 100644 --- a/Modules/Simulation/mitkSimulationDrawTool.cpp +++ b/Modules/Simulation/mitkSimulationDrawTool.cpp @@ -1,577 +1,577 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkSimulation.h" #include "mitkSimulationDrawTool.h" #include #include #include #include #include #include #include #include #include #include #include mitk::SimulationDrawTool::SimulationDrawTool() : m_PolygonMode(0), m_Wireframe(false), m_Update(true) { } mitk::SimulationDrawTool::~SimulationDrawTool() { m_Actors.clear(); } void mitk::SimulationDrawTool::DisableUpdate() { m_Update = false; } std::vector > mitk::SimulationDrawTool::GetActors() const { return m_Actors; } void mitk::SimulationDrawTool::InitProperty(vtkProperty* property) const { if (m_Wireframe) property->SetRepresentationToWireframe(); else property->SetRepresentationToSurface(); } void mitk::SimulationDrawTool::Reset() { m_Actors.clear(); m_Update = true; } void mitk::SimulationDrawTool::drawPoints(const std::vector& points, float pointSize, const Vec4f color) { if (!m_Update || points.empty()) return; unsigned int numPoints = points.size(); - vtkSmartPointer vtkPoints = vtkSmartPointer<::vtkPoints>::New(); + vtkSmartPointer vtkPoints = vtkSmartPointer< ::vtkPoints>::New(); vtkPoints->SetNumberOfPoints(numPoints); vtkSmartPointer cellArray = vtkSmartPointer::New(); for (unsigned int i = 0; i < numPoints; ++i) { vtkPoints->SetPoint(i, points[i].elems); cellArray->InsertNextCell(1); cellArray->InsertCellPoint(i); } vtkSmartPointer polyData = vtkSmartPointer::New(); polyData->SetPoints(vtkPoints); polyData->SetVerts(cellArray); vtkSmartPointer polyDataMapper = vtkSmartPointer::New(); polyDataMapper->SetInput(polyData); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(polyDataMapper); actor->SetScale(Simulation::ScaleFactor); vtkProperty* property = actor->GetProperty(); property->SetColor(color.x(), color.y(), color.z()); property->SetPointSize(pointSize); m_Actors.push_back(actor); } void mitk::SimulationDrawTool::drawLines(const std::vector& points, float lineWidth, const Vec4f color) { if (!m_Update || points.empty()) return; unsigned int numPoints = points.size(); std::vector indices; for (unsigned int i = 0; i < numPoints; i += 2) indices.push_back(Vec2i(i, i + 1)); this->drawLines(points, indices, lineWidth, color); } void mitk::SimulationDrawTool::drawLines(const std::vector& points, const std::vector& indices, float lineWidth, const Vec4f color) { if (!m_Update || points.empty()) return; unsigned int numPoints = points.size(); - vtkSmartPointer vtkPoints = vtkSmartPointer<::vtkPoints>::New(); + vtkSmartPointer vtkPoints = vtkSmartPointer< ::vtkPoints>::New(); vtkPoints->SetNumberOfPoints(numPoints); for (unsigned int i = 0; i < numPoints; ++i) vtkPoints->SetPoint(i, points[i].elems); vtkSmartPointer polyData = vtkSmartPointer::New(); polyData->SetPoints(vtkPoints); vtkSmartPointer lines = vtkSmartPointer::New(); unsigned int numIndices = indices.size(); for (unsigned int i = 0; i < numIndices; ++i) { lines->InsertNextCell(2); lines->InsertCellPoint(indices[i].elems[0]); lines->InsertCellPoint(indices[i].elems[1]); } polyData->SetLines(lines); vtkSmartPointer polyDataMapper = vtkSmartPointer::New(); polyDataMapper->SetInput(polyData); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(polyDataMapper); actor->SetScale(Simulation::ScaleFactor); vtkProperty* property = actor->GetProperty(); property->SetLineWidth(lineWidth); property->SetColor(color.x(), color.y(), color.z()); m_Actors.push_back(actor); } void mitk::SimulationDrawTool::drawTriangles(const std::vector& points, const Vec4f color) { if (!m_Update || points.empty()) return; unsigned int numPoints = points.size(); - vtkSmartPointer vtkPoints = vtkSmartPointer<::vtkPoints>::New(); + vtkSmartPointer vtkPoints = vtkSmartPointer< ::vtkPoints>::New(); vtkPoints->SetNumberOfPoints(numPoints); for (unsigned int i = 0; i < numPoints; ++i) vtkPoints->SetPoint(i, points[i].elems); vtkSmartPointer polyData = vtkSmartPointer::New(); polyData->SetPoints(vtkPoints); vtkSmartPointer triangles = vtkSmartPointer::New(); for (unsigned int i = 0; i < points.size(); i += 3) { triangles->InsertNextCell(3); triangles->InsertCellPoint(i); triangles->InsertCellPoint(i + 1); triangles->InsertCellPoint(i + 2); } polyData->SetPolys(triangles); vtkSmartPointer polyDataNormals = vtkSmartPointer::New(); polyDataNormals->ComputeCellNormalsOff(); polyDataNormals->SetInput(polyData); polyDataNormals->SplittingOff(); vtkSmartPointer polyDataMapper = vtkSmartPointer::New(); polyDataMapper->SetInput(polyDataNormals->GetOutput()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(polyDataMapper); actor->SetScale(Simulation::ScaleFactor); vtkProperty* property = actor->GetProperty(); this->InitProperty(property); property->SetColor(color.x(), color.y(), color.z()); m_Actors.push_back(actor); } void mitk::SimulationDrawTool::drawTriangles(const std::vector& points, const Vector3 normal, const Vec4f color) { if (!m_Update || points.empty()) return; unsigned int numPoints = points.size(); unsigned int numNormals = numPoints / 3; - vtkSmartPointer vtkPoints = vtkSmartPointer<::vtkPoints>::New(); + vtkSmartPointer vtkPoints = vtkSmartPointer< ::vtkPoints>::New(); vtkPoints->SetNumberOfPoints(numPoints); for (unsigned int i = 0; i < numPoints; ++i) vtkPoints->SetPoint(i, points[i].elems); vtkSmartPointer polyData = vtkSmartPointer::New(); polyData->SetPoints(vtkPoints); vtkSmartPointer triangles = vtkSmartPointer::New(); for (unsigned int i = 0; i < points.size(); i += 3) { triangles->InsertNextCell(3); triangles->InsertCellPoint(i); triangles->InsertCellPoint(i + 1); triangles->InsertCellPoint(i + 2); } polyData->SetPolys(triangles); vtkSmartPointer normals = vtkSmartPointer::New(); normals->SetNumberOfComponents(3); normals->SetNumberOfTuples(numNormals); normals->SetName("Normals"); for (unsigned int i = 0; i < numNormals; ++i) normals->SetTuple(i, normal.elems); polyData->GetCellData()->SetNormals(normals); vtkSmartPointer polyDataMapper = vtkSmartPointer::New(); polyDataMapper->SetInput(polyData); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(polyDataMapper); actor->SetScale(Simulation::ScaleFactor); vtkProperty* property = actor->GetProperty(); this->InitProperty(property); property->SetColor(color.x(), color.y(), color.z()); m_Actors.push_back(actor); } void mitk::SimulationDrawTool::drawTriangles(const std::vector& points, const std::vector& indices, const std::vector& normals, const Vec4f color) { if (!m_Update || points.empty() || indices.empty() || normals.empty()) return; unsigned int numPoints = points.size(); - vtkSmartPointer vtkPoints = vtkSmartPointer<::vtkPoints>::New(); + vtkSmartPointer vtkPoints = vtkSmartPointer< ::vtkPoints>::New(); vtkPoints->SetNumberOfPoints(numPoints); for (unsigned int i = 0; i < numPoints; ++i) vtkPoints->SetPoint(i, points[i].elems); vtkSmartPointer polyData = vtkSmartPointer::New(); polyData->SetPoints(vtkPoints); vtkSmartPointer triangles = vtkSmartPointer::New(); unsigned int numIndices = indices.size(); for (unsigned int i = 0; i < numIndices; ++i) { triangles->InsertNextCell(3); triangles->InsertCellPoint(indices[i].elems[0]); triangles->InsertCellPoint(indices[i].elems[1]); triangles->InsertCellPoint(indices[i].elems[2]); } polyData->SetPolys(triangles); unsigned int numNormals = normals.size(); vtkSmartPointer vtkNormals = vtkSmartPointer::New(); vtkNormals->SetNumberOfComponents(3); vtkNormals->SetNumberOfTuples(numNormals); vtkNormals->SetName("Normals"); for (unsigned int i = 0; i < numNormals; ++i) vtkNormals->SetTuple(i, normals[i].elems); polyData->GetCellData()->SetNormals(vtkNormals); vtkSmartPointer polyDataMapper = vtkSmartPointer::New(); polyDataMapper->SetInput(polyData); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(polyDataMapper); actor->SetScale(Simulation::ScaleFactor); vtkProperty* property = actor->GetProperty(); this->InitProperty(property); property->SetColor(color.x(), color.y(), color.z()); m_Actors.push_back(actor); } void mitk::SimulationDrawTool::drawTriangles(const std::vector&, const std::vector&, const std::vector&) { } void mitk::SimulationDrawTool::drawTriangleStrip(const std::vector&, const std::vector&, const Vec4f) { } void mitk::SimulationDrawTool::drawTriangleFan(const std::vector&, const std::vector&, const Vec4f) { } void mitk::SimulationDrawTool::drawFrame(const Vector3& position, const Quaternion& orientation, const Vec3f& size) { if (!m_Update) return; float minSize = std::min(std::min(size.x(), size.y()), size.z()); float maxSize = std::max(std::max(size.x(), size.y()), size.z()); if (maxSize > minSize * 2.0f) { if (minSize > 0.0f) maxSize = minSize * 2.0f; else minSize = maxSize * 0.707f; } const float radii[] = { minSize * 0.1f, maxSize * 0.2f }; bool wireframeBackup = m_Wireframe; m_Wireframe = false; if (size.x() != 0.0f) { Vector3 point2 = position + orientation.rotate(Vec3f(size.x(), 0.0f, 0.0f)); Vector3 point3 = point2 + orientation.rotate(Vec3f(radii[1], 0.0f, 0.0f)); Vec4f red(1.0f, 0.0f, 0.0f, 1.0f); this->drawCylinder(position, point2, radii[0], red); this->drawCone(point2, point3, radii[1], 0.0f, red); } if (size.y() != 0.0f) { Vector3 point2 = position + orientation.rotate(Vec3f(0.0f, size.y(), 0.0f)); Vector3 point3 = point2 + orientation.rotate(Vec3f(0.0f, radii[1], 0.0f)); Vec4f green(0.0f, 1.0f, 0.0f, 1.0f); this->drawCylinder(position, point2, radii[0], green); this->drawCone(point2, point3, radii[1], 0.0f, green); } if (size.z() != 0.0f) { Vector3 point2 = position + orientation.rotate(Vec3f(0.0f, 0.0f, size.z())); Vector3 point3 = point2 + orientation.rotate(Vec3f(0.0f, 0.0f, radii[1])); Vec4f blue(0.0f, 0.0f, 1.0f, 1.0f); this->drawCylinder(position, point2, radii[0], blue); this->drawCone(point2, point3, radii[1], 0.0f, blue); } m_Wireframe = wireframeBackup; } void mitk::SimulationDrawTool::drawSpheres(const std::vector& points, const std::vector& radii, const Vec4f color) { if (!m_Update || points.empty()) return; unsigned int numSpheres = points.size(); for (unsigned int i = 0; i < numSpheres; ++i) { vtkSmartPointer sphereSource = vtkSmartPointer::New(); sphereSource->SetCenter(const_cast(points[i].elems)); sphereSource->SetRadius(radii[i]); sphereSource->SetPhiResolution(16); sphereSource->SetThetaResolution(32); sphereSource->LatLongTessellationOn(); vtkSmartPointer polyDataMapper = vtkSmartPointer::New(); polyDataMapper->SetInputConnection(sphereSource->GetOutputPort()); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(polyDataMapper); actor->SetScale(Simulation::ScaleFactor); vtkProperty* property = actor->GetProperty(); this->InitProperty(property); property->SetColor(color.x(), color.y(), color.z()); m_Actors.push_back(actor); } } void mitk::SimulationDrawTool::drawSpheres(const std::vector& points, float radius, const Vec4f color) { if (!m_Update || points.empty()) return; unsigned int numPoints = points.size(); std::vector radii(numPoints, radius); this->drawSpheres(points, radii, color); } void mitk::SimulationDrawTool::drawCone(const Vector3& point1, const Vector3& point2, float radius1, float radius2, const Vec4f color, int subdivisions) { if (!m_Update) return; vtkSmartPointer points = vtkSmartPointer::New(); points->SetNumberOfPoints(2); points->SetPoint(0, point1.elems); points->SetPoint(1, point2.elems); vtkSmartPointer line = vtkSmartPointer::New(); line->InsertNextCell(2); line->InsertCellPoint(0); line->InsertCellPoint(1); vtkSmartPointer polyData = vtkSmartPointer::New(); polyData->SetPoints(points); polyData->SetLines(line); const char* radiiName = "Radii"; vtkSmartPointer radii = vtkSmartPointer::New(); radii->SetName(radiiName); radii->SetNumberOfTuples(2); radii->SetTuple1(0, radius1); radii->SetTuple1(1, radius2); vtkPointData* pointData = polyData->GetPointData(); pointData->AddArray(radii); pointData->SetActiveScalars(radiiName); vtkSmartPointer tubeFilter = vtkSmartPointer::New(); tubeFilter->SetInput(polyData); tubeFilter->CappingOn(); tubeFilter->SetNumberOfSides(subdivisions); tubeFilter->SetVaryRadiusToVaryRadiusByAbsoluteScalar(); vtkSmartPointer polyDataMapper = vtkSmartPointer::New(); polyDataMapper->SetInputConnection(tubeFilter->GetOutputPort()); polyDataMapper->ScalarVisibilityOff(); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper(polyDataMapper); actor->SetScale(Simulation::ScaleFactor); vtkProperty* property = actor->GetProperty(); this->InitProperty(property); property->SetColor(color.x(), color.y(), color.z()); m_Actors.push_back(actor); } void mitk::SimulationDrawTool::drawCube(const float&, const Vec4f&, const int&) { } void mitk::SimulationDrawTool::drawCylinder(const Vector3& point1, const Vector3& point2, float radius, const Vec4f color, int subdivisions) { if (!m_Update) return; this->drawCone(point1, point2, radius, radius, color, subdivisions); } void mitk::SimulationDrawTool::drawCapsule(const Vector3&, const Vector3&, float, const Vec4f, int) { } void mitk::SimulationDrawTool::drawArrow(const Vector3& point1, const Vector3& point2, float radius, const Vec4f color, int subdivisions) { if (!m_Update) return; Vector3 point3 = point1 * 0.2f + point2 * 0.8f; this->drawCylinder(point1, point3, radius, color, subdivisions); this->drawCone(point3, point2, radius * 2.5f, 0.0f, color, subdivisions); } void mitk::SimulationDrawTool::drawPlus(const float& edgeRadius, const Vec4f& color, const int& subdivisions) { if (!m_Update) return; this->drawCylinder(Vector3(-1.0, 0.0, 0.0), Vector3(1.0, 0.0, 0.0), edgeRadius, color, subdivisions); this->drawCylinder(Vector3(0.0, -1.0, 0.0), Vector3(0.0, 1.0, 0.0), edgeRadius, color, subdivisions); this->drawCylinder(Vector3(0.0, 0.0, -1.0), Vector3(0.0, 0.0, 1.0), edgeRadius, color, subdivisions); } void mitk::SimulationDrawTool::drawPoint(const Vector3&, const Vec4f&) { } void mitk::SimulationDrawTool::drawPoint(const Vector3&, const Vector3&, const Vec4f&) { } void mitk::SimulationDrawTool::drawTriangle(const Vector3&, const Vector3&, const Vector3&, const Vector3&) { } void mitk::SimulationDrawTool::drawTriangle(const Vector3&, const Vector3&, const Vector3&, const Vector3&, const Vec4f&) { } void mitk::SimulationDrawTool::drawTriangle(const Vector3&, const Vector3&, const Vector3&, const Vector3&, const Vec4f&, const Vec4f&, const Vec4f&) { } void mitk::SimulationDrawTool::drawSphere(const Vector3&, float) { } void mitk::SimulationDrawTool::pushMatrix() { } void mitk::SimulationDrawTool::popMatrix() { } void mitk::SimulationDrawTool::multMatrix(float*) { } void mitk::SimulationDrawTool::scale(float) { } void mitk::SimulationDrawTool::setMaterial(const Vec4f&, std::string) { } void mitk::SimulationDrawTool::resetMaterial(const Vec4f&, std::string) { } void mitk::SimulationDrawTool::setPolygonMode(int mode, bool wireframe) { if (!m_Update) return; m_PolygonMode = mode; m_Wireframe = wireframe; } void mitk::SimulationDrawTool::setLightingEnabled(bool) { } void mitk::SimulationDrawTool::writeOverlayText(int, int, unsigned int, const Vec4f&, const char*) { } diff --git a/Modules/ToFProcessing/Documentation/CMakeLists.txt b/Modules/ToFProcessing/Documentation/CMakeLists.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.cpp b/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.cpp index 99a07bc4a7..2b24b19331 100644 --- a/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.cpp +++ b/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.cpp @@ -1,296 +1,301 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include #include #include mitk::ToFDistanceImageToSurfaceFilter::ToFDistanceImageToSurfaceFilter() : m_IplScalarImage(NULL), m_CameraIntrinsics(), m_TextureImageWidth(0), m_TextureImageHeight(0), m_InterPixelDistance(), m_TextureIndex(0) { m_InterPixelDistance.Fill(0.045); m_CameraIntrinsics = mitk::CameraIntrinsics::New(); m_CameraIntrinsics->SetFocalLength(295.78960196187319,296.1255427948447); m_CameraIntrinsics->SetFocalLength(5.9421434211923247e+02,5.9104053696870778e+02); m_CameraIntrinsics->SetPrincipalPoint(3.3930780975300314e+02,2.4273913761751615e+02); m_CameraIntrinsics->SetDistorsionCoeffs(-0.36874385358645773f,-0.14339503290129013,0.0033210108720361795,-0.004277703352074105); m_ReconstructionMode = WithInterPixelDistance; } mitk::ToFDistanceImageToSurfaceFilter::~ToFDistanceImageToSurfaceFilter() { } void mitk::ToFDistanceImageToSurfaceFilter::SetInput( Image* distanceImage, mitk::CameraIntrinsics::Pointer cameraIntrinsics ) { this->SetCameraIntrinsics(cameraIntrinsics); this->SetInput(0,distanceImage); } void mitk::ToFDistanceImageToSurfaceFilter::SetInput( unsigned int idx, Image* distanceImage, mitk::CameraIntrinsics::Pointer cameraIntrinsics ) { this->SetCameraIntrinsics(cameraIntrinsics); this->SetInput(idx,distanceImage); } void mitk::ToFDistanceImageToSurfaceFilter::SetInput( mitk::Image* distanceImage ) { this->SetInput(0,distanceImage); } void mitk::ToFDistanceImageToSurfaceFilter::SetInput( unsigned int idx, mitk::Image* distanceImage ) { if ((distanceImage == NULL) && (idx == this->GetNumberOfInputs() - 1)) // if the last input is set to NULL, reduce the number of inputs by one this->SetNumberOfInputs(this->GetNumberOfInputs() - 1); else this->ProcessObject::SetNthInput(idx, distanceImage); // Process object is not const-correct so the const_cast is required here this->CreateOutputsForAllInputs(); } mitk::Image* mitk::ToFDistanceImageToSurfaceFilter::GetInput() { return this->GetInput(0); } mitk::Image* mitk::ToFDistanceImageToSurfaceFilter::GetInput( unsigned int idx ) { if (this->GetNumberOfInputs() < 1) { mitkThrow() << "No input given for ToFDistanceImageToSurfaceFilter"; } return static_cast< mitk::Image*>(this->ProcessObject::GetInput(idx)); } void mitk::ToFDistanceImageToSurfaceFilter::GenerateData() { mitk::Surface::Pointer output = this->GetOutput(); assert(output); mitk::Image::Pointer input = this->GetInput(); assert(input); // mesh points int xDimension = input->GetDimension(0); int yDimension = input->GetDimension(1); unsigned int size = xDimension*yDimension; //size of the image-array std::vector isPointValid; isPointValid.resize(size); vtkSmartPointer points = vtkSmartPointer::New(); points->SetDataTypeToDouble(); vtkSmartPointer polys = vtkSmartPointer::New(); vtkSmartPointer scalarArray = vtkSmartPointer::New(); vtkSmartPointer textureCoords = vtkSmartPointer::New(); textureCoords->SetNumberOfComponents(2); textureCoords->Allocate(size); //Make a vtkIdList to save the ID's of the polyData corresponding to the image //pixel ID's. See below for more documentation. - vtkSmartPointer vertexIdList = vtkSmartPointer::New(); + m_VertexIdList = vtkSmartPointer::New(); //Allocate the object once else it would automatically allocate new memory //for every vertex and perform a copy which is expensive. - vertexIdList->Allocate(size); + m_VertexIdList->Allocate(size); + m_VertexIdList->SetNumberOfIds(size); + for(int i = 0; i < size; ++i) + { + m_VertexIdList->SetId(i, 0); + } float* scalarFloatData = NULL; if (this->m_IplScalarImage) // if scalar image is defined use it for texturing { scalarFloatData = (float*)this->m_IplScalarImage->imageData; } else if (this->GetInput(m_TextureIndex)) // otherwise use intensity image (input(2)) { scalarFloatData = (float*)this->GetInput(m_TextureIndex)->GetData(); } float* inputFloatData = (float*)(input->GetSliceData(0, 0, 0)->GetData()); //calculate world coordinates mitk::ToFProcessingCommon::ToFPoint2D focalLengthInPixelUnits; mitk::ToFProcessingCommon::ToFScalarType focalLengthInMm; if((m_ReconstructionMode == WithOutInterPixelDistance) || (m_ReconstructionMode == Kinect)) { focalLengthInPixelUnits[0] = m_CameraIntrinsics->GetFocalLengthX(); focalLengthInPixelUnits[1] = m_CameraIntrinsics->GetFocalLengthY(); } else if( m_ReconstructionMode == WithInterPixelDistance) { //convert focallength from pixel to mm focalLengthInMm = (m_CameraIntrinsics->GetFocalLengthX()*m_InterPixelDistance[0]+m_CameraIntrinsics->GetFocalLengthY()*m_InterPixelDistance[1])/2.0; } mitk::ToFProcessingCommon::ToFPoint2D principalPoint; principalPoint[0] = m_CameraIntrinsics->GetPrincipalPointX(); principalPoint[1] = m_CameraIntrinsics->GetPrincipalPointY(); mitk::Point3D origin = input->GetGeometry()->GetOrigin(); for (int j=0; jInsertPoint(pixelID, cartesianCoordinates.GetDataPointer()). //If we use points->InsertNextPoint(...) instead, the ID's do not //correspond to the image pixel ID's. Thus, we have to save them //in the vertexIdList. - vertexIdList->InsertId(pixelID, points->InsertNextPoint(cartesianCoordinates.GetDataPointer())); + m_VertexIdList->SetId(pixelID, points->InsertNextPoint(cartesianCoordinates.GetDataPointer())); if((i >= 1) && (j >= 1)) { //This little piece of art explains the ID's: // // P(x_1y_1)---P(xy_1) // | | // | | // | | // P(x_1y)-----P(xy) // //We can only start triangulation if we are at vertex (1,1), //because we need the other 3 vertices near this one. //To go one pixel line back in the image array, we have to //subtract 1x xDimension. vtkIdType xy = pixelID; vtkIdType x_1y = pixelID-1; vtkIdType xy_1 = pixelID-xDimension; vtkIdType x_1y_1 = xy_1-1; //Find the corresponding vertex ID's in the saved vertexIdList: - vtkIdType xyV = vertexIdList->GetId(xy); - vtkIdType x_1yV = vertexIdList->GetId(x_1y); - vtkIdType xy_1V = vertexIdList->GetId(xy_1); - vtkIdType x_1y_1V = vertexIdList->GetId(x_1y_1); + vtkIdType xyV = m_VertexIdList->GetId(xy); + vtkIdType x_1yV = m_VertexIdList->GetId(x_1y); + vtkIdType xy_1V = m_VertexIdList->GetId(xy_1); + vtkIdType x_1y_1V = m_VertexIdList->GetId(x_1y_1); if (isPointValid[xy]&&isPointValid[x_1y]&&isPointValid[x_1y_1]&&isPointValid[xy_1]) // check if points of cell are valid { polys->InsertNextCell(3); polys->InsertCellPoint(x_1yV); polys->InsertCellPoint(xyV); polys->InsertCellPoint(x_1y_1V); polys->InsertNextCell(3); polys->InsertCellPoint(x_1y_1V); polys->InsertCellPoint(xyV); polys->InsertCellPoint(xy_1V); } } //Scalar values are necessary for mapping colors/texture onto the surface if (scalarFloatData) { - scalarArray->InsertTuple1(vertexIdList->GetId(pixelID), scalarFloatData[pixelID]); + scalarArray->InsertTuple1(m_VertexIdList->GetId(pixelID), scalarFloatData[pixelID]); } //These Texture Coordinates will map color pixel and vertices 1:1 (e.g. for Kinect). float xNorm = (((float)i)/xDimension);// correct video texture scale for kinect float yNorm = ((float)j)/yDimension; //don't flip. we don't need to flip. - textureCoords->InsertTuple2(vertexIdList->GetId(pixelID), xNorm, yNorm); + textureCoords->InsertTuple2(m_VertexIdList->GetId(pixelID), xNorm, yNorm); } } } vtkSmartPointer mesh = vtkSmartPointer::New(); mesh->SetPoints(points); mesh->SetPolys(polys); //Pass the scalars to the polydata (if they were set). if (scalarArray->GetNumberOfTuples()>0) { mesh->GetPointData()->SetScalars(scalarArray); } //Pass the TextureCoords to the polydata anyway (to save them). mesh->GetPointData()->SetTCoords(textureCoords); output->SetVtkPolyData(mesh); } void mitk::ToFDistanceImageToSurfaceFilter::CreateOutputsForAllInputs() { this->SetNumberOfOutputs(this->GetNumberOfInputs()); // create outputs for all inputs for (unsigned int idx = 0; idx < this->GetNumberOfOutputs(); ++idx) if (this->GetOutput(idx) == NULL) { DataObjectPointer newOutput = this->MakeOutput(idx); this->SetNthOutput(idx, newOutput); } this->Modified(); } void mitk::ToFDistanceImageToSurfaceFilter::GenerateOutputInformation() { this->GetOutput(); itkDebugMacro(<<"GenerateOutputInformation()"); } void mitk::ToFDistanceImageToSurfaceFilter::SetScalarImage(IplImage* iplScalarImage) { this->m_IplScalarImage = iplScalarImage; this->Modified(); } IplImage* mitk::ToFDistanceImageToSurfaceFilter::GetScalarImage() { return this->m_IplScalarImage; } void mitk::ToFDistanceImageToSurfaceFilter::SetTextureImageWidth(int width) { this->m_TextureImageWidth = width; } void mitk::ToFDistanceImageToSurfaceFilter::SetTextureImageHeight(int height) { this->m_TextureImageHeight = height; } diff --git a/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.h b/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.h index 0dc4de56ed..9f12e4b86c 100644 --- a/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.h +++ b/Modules/ToFProcessing/mitkToFDistanceImageToSurfaceFilter.h @@ -1,163 +1,172 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef __mitkToFDistanceImageToSurfaceFilter_h #define __mitkToFDistanceImageToSurfaceFilter_h #include #include #include #include #include #include "mitkCameraIntrinsics.h" #include #include +#include +#include + namespace mitk { /** * @brief Converts a Time-of-Flight (ToF) distance image to a 3D surface using the pinhole camera model for coordinate computation. * The intrinsic parameters of the camera (FocalLength, PrincipalPoint, InterPixelDistance) are set via SetCameraIntrinsics(). The * measured distance for each pixel corresponds to the distance between the object point and the corresponding image point on the * image plane. * * The coordinate conversion follows the model of a common pinhole camera where the origin of the camera * coordinate system (world coordinates) is at the pinhole * \image html ../Modules/ToFProcessing/Documentation/PinholeCameraModel.png * The definition of the image plane and its coordinate systems (pixel and mm) is depicted in the following image * \image html ../Modules/ToFProcessing/Documentation/ImagePlane.png * * @ingroup SurfaceFilters * @ingroup ToFProcessing */ class mitkToFProcessing_EXPORT ToFDistanceImageToSurfaceFilter : public SurfaceSource { public: mitkClassMacro( ToFDistanceImageToSurfaceFilter , SurfaceSource ); itkNewMacro( Self ); itkSetMacro(CameraIntrinsics, mitk::CameraIntrinsics::Pointer); itkGetMacro(CameraIntrinsics, mitk::CameraIntrinsics::Pointer); itkSetMacro(InterPixelDistance,ToFProcessingCommon::ToFPoint2D); itkGetMacro(InterPixelDistance,ToFProcessingCommon::ToFPoint2D); itkSetMacro(TextureIndex,int); + itkSetMacro(VertexIdList, vtkSmartPointer); + itkGetMacro(VertexIdList, vtkSmartPointer); + /** * @brief The ReconstructionModeType enum: Defines the reconstruction mode, if using no interpixeldistances and focal lenghts in pixel units or interpixeldistances and focal length in mm. The Kinect option defines a special reconstruction mode for the kinect. */ enum ReconstructionModeType{ WithOutInterPixelDistance = 1, WithInterPixelDistance = 2, Kinect = 3}; itkSetEnumMacro(ReconstructionMode,ReconstructionModeType); itkGetEnumMacro(ReconstructionMode,ReconstructionModeType); /*! \brief Set scalar image used as texture of the surface. \param iplScalarImage OpenCV image for texturing */ void SetScalarImage(IplImage* iplScalarImage); /*! \brief Set scalar image used as texture of the surface. \return OpenCV image for texturing */ IplImage* GetScalarImage(); /*! \brief Set width of the scalar image used for texturing the surface \param width width (x-dimension) of the texture image */ void SetTextureImageWidth(int width); /*! \brief Set height of the scalar image used for texturing the surface \param height height (y-dimension) of the texture image */ void SetTextureImageHeight(int height); /*! \brief Sets the input of this filter \param distanceImage input is the distance image of e.g. a ToF camera */ virtual void SetInput( Image* distanceImage); /*! \brief Sets the input of this filter and the intrinsic parameters \param distanceImage input is the distance image of e.g. a ToF camera */ virtual void SetInput( Image* distanceImage, mitk::CameraIntrinsics::Pointer cameraIntrinsics ); /*! \brief Sets the input of this filter at idx \param idx number of the current input \param distanceImage input is the distance image of e.g. a ToF camera */ virtual void SetInput(unsigned int idx, Image* distanceImage); /*! \brief Sets the input of this filter at idx and the intrinsic parameters \param idx number of the current input \param distanceImage input is the distance image of e.g. a ToF camera \param cameraIntrinsics This is the camera model which holds parameters like focal length, pixel size, etc. which are needed for the reconstruction of the surface. */ virtual void SetInput( unsigned int idx, Image* distanceImage, mitk::CameraIntrinsics::Pointer cameraIntrinsics ); /*! \brief Returns the input of this filter */ Image* GetInput(); /*! \brief Returns the input with id idx of this filter */ Image* GetInput(unsigned int idx); protected: /*! \brief Standard constructor */ ToFDistanceImageToSurfaceFilter(); /*! \brief Standard destructor */ ~ToFDistanceImageToSurfaceFilter(); virtual void GenerateOutputInformation(); /*! \brief Method generating the output of this filter. Called in the updated process of the pipeline. This method generates the output of the ToFSurfaceSource: The generated surface of the 3d points */ virtual void GenerateData(); /** * \brief Create an output for each input * * This Method sets the number of outputs to the number of inputs * and creates missing outputs objects. * \warning any additional outputs that exist before the method is called are deleted */ void CreateOutputsForAllInputs(); IplImage* m_IplScalarImage; ///< Scalar image used for surface texturing mitk::CameraIntrinsics::Pointer m_CameraIntrinsics; ///< Specifies the intrinsic parameters int m_TextureImageWidth; ///< Width (x-dimension) of the texture image int m_TextureImageHeight; ///< Height (y-dimension) of the texture image ToFProcessingCommon::ToFPoint2D m_InterPixelDistance; ///< distance in mm between two adjacent pixels on the ToF camera chip int m_TextureIndex; ///< Index of the input used as texture image when no scalar image was set via SetIplScalarImage(). 0 = Distance, 1 = Amplitude, 2 = Intensity ReconstructionModeType m_ReconstructionMode; ///< The ReconstructionModeType enum: Defines the reconstruction mode, if using no interpixeldistances and focal lenghts in pixel units or interpixeldistances and focal length in mm. The Kinect option defines a special reconstruction mode for the kinect. + + vtkSmartPointer m_VertexIdList; ///< Make a vtkIdList to save the ID's of the polyData corresponding to the image pixel ID's. This can be accessed after generate data to obtain the mapping. + }; } //END mitk namespace #endif diff --git a/Modules/ToFProcessing/mitkToFProcessingCommon.h b/Modules/ToFProcessing/mitkToFProcessingCommon.h index 3f45304a2b..cd49cd9a47 100644 --- a/Modules/ToFProcessing/mitkToFProcessingCommon.h +++ b/Modules/ToFProcessing/mitkToFProcessingCommon.h @@ -1,335 +1,335 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKTOFPROCESSINGCOMMON_H #define MITKTOFPROCESSINGCOMMON_H #include "mitkToFProcessingExports.h" #include "mitkVector.h" #include namespace mitk { /** * @brief Helper class providing functions which are useful for multiple usage * * Currently the following methods are provided: *
    *
  • Conversion from 2D image coordinates to 3D world coordinates (IndexToCartesianCoordinates()) *
  • Conversion from 3D world coordinates to 2D image coordinates (CartesianToIndexCoordinates()) *
* The coordinate conversion follows the model of a common pinhole camera where the origin of the camera * coordinate system (world coordinates) is at the pinhole * \image html ../Modules/ToFProcessing/Documentation/PinholeCameraModel.png * The definition of the image plane and its coordinate systems (pixel and mm) is depicted in the following image * \image html ../Modules/ToFProcessing/Documentation/ImagePlane.png * @ingroup ToFProcessing */ class mitkToFProcessing_EXPORT ToFProcessingCommon { public: typedef double ToFScalarType; typedef itk::Point ToFPoint2D; typedef itk::Point ToFPoint3D; typedef itk::Vector ToFVector2D; typedef itk::Vector ToFVector3D; /*! \brief Convert index based distances to cartesian coordinates \param i index in x direction of image plane \param j index in y direction of image plane \param distance distance value at given index in mm \param focalLengthX focal length of optical system in pixel units in x-direction (mostly obtained from camera calibration) \param focalLengthY focal length of optical system in pixel units in y-direction (mostly obtained from camera calibration) \param principalPointX x coordinate of principal point on image plane in pixel \param principalPointY y coordinate of principal point on image plane in pixel \return cartesian coordinates for current index will be written here */ static ToFPoint3D IndexToCartesianCoordinates(unsigned int i, unsigned int j, ToFScalarType distance, ToFScalarType focalLengthX, ToFScalarType focalLengthY, ToFScalarType principalPointX, ToFScalarType principalPointY); /*! \brief Convert index based distances to cartesian coordinates \param i index in x direction of image plane \param j index in y direction of image plane \param distance distance value at given index in mm \param focalLength focal length of optical system in pixel units (mostly obtained from camera calibration) \param principalPoint coordinates of principal point on image plane in pixel \return cartesian coordinates for current index will be written here */ inline static ToFPoint3D IndexToCartesianCoordinates(unsigned int i, unsigned int j, ToFScalarType distance, ToFPoint2D focalLength, ToFPoint2D principalPoint) { return IndexToCartesianCoordinates(i,j,distance,focalLength[0],focalLength[1],principalPoint[0],principalPoint[1]); } /*! \brief Convert index based distances to cartesian coordinates \param index index coordinates \param distance distance value at given index in mm \param focalLength focal length of optical system in pixel units (mostly obtained from camera calibration) \param principalPoint coordinates of principal point on image plane in pixel \return cartesian coordinates for current index will be written here */ inline static ToFPoint3D IndexToCartesianCoordinates(mitk::Index3D index, ToFScalarType distance, ToFPoint2D focalLength, ToFPoint2D principalPoint) { return IndexToCartesianCoordinates(index[0],index[1],distance,focalLength[0],focalLength[1],principalPoint[0], principalPoint[1]); } /*! \brief Convenience method to convert index based distances to cartesian coordinates using array as input \param i index in x direction of image plane \param j index in y direction of image plane \param distance distance value at given index in mm \param focalLength focal length of optical system in pixel units (mostly obtained from camera calibration) \param principalPoint coordinates of principal point on image plane in pixel \return cartesian coordinates for current index will be written here */ inline static ToFPoint3D IndexToCartesianCoordinates(unsigned int i, unsigned int j, ToFScalarType distance, ToFScalarType focalLength[2], ToFScalarType principalPoint[2]) { return IndexToCartesianCoordinates(i,j,distance,focalLength[0],focalLength[1],principalPoint[0],principalPoint[1]); } /*! \brief Convert index based distances to cartesian coordinates \param i index in x direction of image plane \param j index in y direction of image plane \param distance distance value at given index in mm \param focalLength focal length of optical system in mm (mostly obtained from camera calibration) \param interPixelDistanceX distance in x direction between adjacent pixels in mm \param interPixelDistanceY distance in y direction between adjacent pixels in mm \param principalPointX x coordinate of principal point on image plane in pixel \param principalPointY y coordinate of principal point on image plane in pixel \return cartesian coordinates for current index will be written here */ static ToFPoint3D IndexToCartesianCoordinatesWithInterpixdist(unsigned int i, unsigned int j, ToFScalarType distance, ToFScalarType focalLength, ToFScalarType interPixelDistanceX, ToFScalarType interPixelDistanceY, ToFScalarType principalPointX, ToFScalarType principalPointY); /*! \brief Convert index based distances to cartesian coordinates \param i index in x direction of image plane \param j index in y direction of image plane \param distance distance value at given index in mm \param focalLength focal length of optical system in mm (mostly obtained from camera calibration) \param interPixelDistance distance between adjacent pixels in mm \param principalPoint coordinates of principal point on image plane in pixel \return cartesian coordinates for current index will be written here */ inline static ToFPoint3D IndexToCartesianCoordinatesWithInterpixdist(unsigned int i, unsigned int j, ToFScalarType distance, ToFScalarType focalLength, ToFPoint2D interPixelDistance, ToFPoint2D principalPoint) { return IndexToCartesianCoordinatesWithInterpixdist(i,j,distance,focalLength,interPixelDistance[0],interPixelDistance[1],principalPoint[0],principalPoint[1]); } /*! \brief Convert index based distances to cartesian coordinates \param index index coordinates \param distance distance value at given index in mm \param focalLength focal length of optical system (mostly obtained from camera calibration) \param interPixelDistance distance between adjacent pixels in mm for x and y direction \param principalPoint coordinates of principal point on image plane in pixel \return cartesian coordinates for current index will be written here */ inline static ToFPoint3D IndexToCartesianCoordinatesWithInterpixdist(mitk::Index3D index, ToFScalarType distance, ToFScalarType focalLength, ToFPoint2D interPixelDistance, ToFPoint2D principalPoint) { return IndexToCartesianCoordinatesWithInterpixdist(index[0],index[1],distance,focalLength,interPixelDistance[0], interPixelDistance[1],principalPoint[0], principalPoint[1]); } /*! \brief Convenience method to convert index based distances to cartesian coordinates using array as input \param i index in x direction of image plane \param j index in y direction of image plane \param distance distance value at given index in mm \param focalLength focal length of optical system in mm (mostly obtained from camera calibration) \param interPixelDistance distance between adjacent pixels in mm \param principalPoint coordinates of principal point on image plane in pixel \return cartesian coordinates for current index will be written here */ inline static ToFPoint3D IndexToCartesianCoordinatesWithInterpixdist(unsigned int i, unsigned int j, ToFScalarType distance, ToFScalarType focalLength, ToFScalarType interPixelDistance[2], ToFScalarType principalPoint[2]) { return IndexToCartesianCoordinatesWithInterpixdist(i,j,distance,focalLength,interPixelDistance[0],interPixelDistance[1],principalPoint[0],principalPoint[1]); } /*! \brief Convert cartesian coordinates to index based distances \param cartesianPointX x coordinate of point (of a surface or point set) to convert in 3D coordinates \param cartesianPointY y coordinate of point (of a surface or point set) to convert in 3D coordinates \param cartesianPointZ z coordinate of point (of a surface or point set) to convert in 3D coordinates \param focalLengthX focal length of optical system in pixel units in x-direction (mostly obtained from camera calibration) \param focalLengthY focal length of optical system in pixel units in y-direction (mostly obtained from camera calibration) \param principalPointX x coordinate of principal point on image plane in pixel \param principalPointY y coordinate of principal point on image plane in pixel \param calculateDistance if this flag is set, the distance value is stored in the z position of the output otherwise z=0 \return a ToFPoint3D. (int)ToFPoint3D[0]+0.5 and (int)ToFPoint3D[0]+0.5 will return the x and y index coordinates. ToFPoint3D[2] contains the distance value */ static ToFPoint3D CartesianToIndexCoordinates(ToFScalarType cartesianPointX, ToFScalarType cartesianPointY,ToFScalarType cartesianPointZ, ToFScalarType focalLengthX, ToFScalarType focalLengthY, ToFScalarType principalPointX, ToFScalarType principalPointY, bool calculateDistance=true); /*! \brief Convenience method to convert cartesian coordinates to index based distances using arrays \param cartesianPoint point (of a surface or point set) to convert in 3D coordinates \param focalLength focal length of optical system in pixel units (mostly obtained from camera calibration) \param principalPoint coordinates of principal point on image plane in pixel \param calculateDistance if this flag is set, the distance value is stored in the z position of the output otherwise z=0 \return a ToFPoint3D. (int)ToFPoint3D[0]+0.5 and (int)ToFPoint3D[0]+0.5 will return the x and y index coordinates. ToFPoint3D[2] contains the distance value */ inline static ToFPoint3D CartesianToIndexCoordinates(ToFScalarType cartesianPoint[3], ToFScalarType focalLength[2], ToFScalarType principalPoint[2], bool calculateDistance=true) { return CartesianToIndexCoordinates(cartesianPoint[0],cartesianPoint[1],cartesianPoint[2],focalLength[0], focalLength[1], principalPoint[0],principalPoint[1],calculateDistance); } /*! \brief Convert cartesian coordinates to index based distances \param cartesianPoint point (of a surface or point set) to convert in 3D coordinates \param focalLength focal length of optical system in pixel units (mostly obtained from camera calibration) \param principalPoint coordinates of principal point on image plane in pixel \param calculateDistance if this flag is set, the distance value is stored in the z position of the output otherwise z=0 \return a ToFPoint3D. (int)ToFPoint3D[0]+0.5 and (int)ToFPoint3D[0]+0.5 will return the x and y index coordinates. ToFPoint3D[2] contains the distance value */ inline static ToFPoint3D CartesianToIndexCoordinates(ToFPoint3D cartesianPoint, ToFPoint2D focalLength, ToFPoint2D principalPoint, bool calculateDistance=true) { return CartesianToIndexCoordinates(cartesianPoint[0],cartesianPoint[1],cartesianPoint[2],focalLength[0], focalLength[1], principalPoint[0],principalPoint[1],calculateDistance); } /*! \brief Convert cartesian coordinates to index based distances \param cartesianPointX x coordinate of point (of a surface or point set) to convert in 3D coordinates \param cartesianPointY y coordinate of point (of a surface or point set) to convert in 3D coordinates \param cartesianPointZ z coordinate of point (of a surface or point set) to convert in 3D coordinates \param focalLength focal length of optical system in mm (mostly obtained from camera calibration) \param interPixelDistanceX distance in x direction between adjacent pixels in mm \param interPixelDistanceY distance in y direction between adjacent pixels in mm \param principalPointX x coordinate of principal point on image plane in pixel \param principalPointY y coordinate of principal point on image plane in pixel \param calculateDistance if this flag is set, the distance value is stored in the z position of the output otherwise z=0 \return a ToFPoint3D. (int)ToFPoint3D[0]+0.5 and (int)ToFPoint3D[0]+0.5 will return the x and y index coordinates. ToFPoint3D[2] contains the distance value */ static ToFPoint3D CartesianToIndexCoordinatesWithInterpixdist(ToFScalarType cartesianPointX, ToFScalarType cartesianPointY,ToFScalarType cartesianPointZ, ToFScalarType focalLength, ToFScalarType interPixelDistanceX, ToFScalarType interPixelDistanceY, ToFScalarType principalPointX, ToFScalarType principalPointY, bool calculateDistance=true); /*! \brief Convenience method to convert cartesian coordinates to index based distances using arrays \param cartesianPoint point (of a surface or point set) to convert in 3D coordinates \param focalLength focal length of optical system in mm (mostly obtained from camera calibration) \param interPixelDistance distance between adjacent pixels in mm for x and y direction \param principalPoint coordinates of principal point on image plane in pixel \param calculateDistance if this flag is set, the distance value is stored in the z position of the output otherwise z=0 \return a ToFPoint3D. (int)ToFPoint3D[0]+0.5 and (int)ToFPoint3D[0]+0.5 will return the x and y index coordinates. ToFPoint3D[2] contains the distance value */ inline static ToFPoint3D CartesianToIndexCoordinatesWithInterpixdist(ToFScalarType cartesianPoint[3], ToFScalarType focalLength, ToFScalarType interPixelDistance[2], ToFScalarType principalPoint[2], bool calculateDistance=true) { return CartesianToIndexCoordinatesWithInterpixdist(cartesianPoint[0],cartesianPoint[1],cartesianPoint[2],focalLength, interPixelDistance[0],interPixelDistance[1],principalPoint[0],principalPoint[1],calculateDistance); } /*! \brief Convert cartesian coordinates to index based distances \param cartesianPoint point (of a surface or point set) to convert in 3D coordinates \param focalLength focal length of optical system in mm (mostly obtained from camera calibration) \param interPixelDistance distance between adjacent pixels in mm for x and y direction \param principalPoint coordinates of principal point on image plane in pixel \param calculateDistance if this flag is set, the distance value is stored in the z position of the output otherwise z=0 \return a ToFPoint3D. (int)ToFPoint3D[0]+0.5 and (int)ToFPoint3D[0]+0.5 will return the x and y index coordinates. ToFPoint3D[2] contains the distance value */ inline static ToFPoint3D CartesianToIndexCoordinatesWithInterpixdist(ToFPoint3D cartesianPoint, ToFScalarType focalLength, ToFPoint2D interPixelDistance, ToFPoint2D principalPoint, bool calculateDistance=true) { return CartesianToIndexCoordinatesWithInterpixdist(cartesianPoint[0],cartesianPoint[1],cartesianPoint[2],focalLength, interPixelDistance[0],interPixelDistance[1],principalPoint[0],principalPoint[1],calculateDistance); } - /** \addtogroup + /** \ingroup KinectReconstruction * @{ * * @brief KinectIndexToCartesianCoordinates Convert a pixel (i,j) with value d to a 3D world point. This conversion is meant for Kinect and slightly different then ToF reconstruction. See also "Hacking the Kinect" - Jeff Kramer, Matt Parker, Daniel Herrera C., Nicolas Burrus, Florian Echtler, Chapter 7, Part 1 "Moving from Depth Map to Point Cloud. * @param i Pixel index i. * @param j Pixel index j. * @param distance Distance value d in mm as obtained from OpenNI. * @param focalLengthX Focallength from calibration. * @param focalLengthY Focallength from calibration. * @param principalPointX Principal point from calibration. * @param principalPointY Principal point from calibration. * @return a ToFPoint3D. The point in world coordinates (mm). */ static ToFProcessingCommon::ToFPoint3D KinectIndexToCartesianCoordinates(unsigned int i, unsigned int j, ToFScalarType distance, ToFScalarType focalLengthX, ToFScalarType focalLengthY, ToFScalarType principalPointX, ToFScalarType principalPointY); inline static ToFPoint3D KinectIndexToCartesianCoordinates(unsigned int i, unsigned int j, ToFScalarType distance, ToFScalarType focalLength[2], ToFScalarType principalPoint[2]) { return KinectIndexToCartesianCoordinates(i,j,distance,focalLength[0],focalLength[1],principalPoint[0],principalPoint[1]); } inline static ToFPoint3D KinectIndexToCartesianCoordinates(unsigned int i, unsigned int j, ToFScalarType distance, ToFPoint2D focalLength, ToFPoint2D principalPoint) { return KinectIndexToCartesianCoordinates(i,j,distance,focalLength[0],focalLength[1],principalPoint[0],principalPoint[1]); } inline static ToFPoint3D KinectIndexToCartesianCoordinates(mitk::Index3D index, ToFScalarType distance, ToFPoint2D focalLength, ToFPoint2D principalPoint) { return KinectIndexToCartesianCoordinates(index[0],index[1],distance,focalLength[0],focalLength[1],principalPoint[0], principalPoint[1]); } /** @}*/ - /** \addtogroup + /** \ingroup KinectReconstructionInverse * @{ * @brief CartesianCoordinatesToKinectIndexCoordinates Transform a 3D world point back to distance image pixel coordinates. * @param cartesianPointX x value of the cartesian point. * @param cartesianPointY y value of the cartesian point. * @param cartesianPointZ z value of the cartesian point. * @param focalLengthX x value of the focal length (from calibration). * @param focalLengthY y value of the focal length (from calibration). * @param principalPointX x value of the principal point (from calibration). * @param principalPointY y value of the principal point (from calibration). * @param calculateDistance Do you want to compute also the distance of the distance image? For Kinect, this value is always the same in cartesian and index coordinates. * @return A ToFPoint3D containing the pixel indices (i,j) in [0] and [1] and (optionally) the distance value in [2] (or just 0.0). */ static ToFPoint3D CartesianToKinectIndexCoordinates(ToFScalarType cartesianPointX, ToFScalarType cartesianPointY, ToFScalarType cartesianPointZ, ToFScalarType focalLengthX, ToFScalarType focalLengthY, ToFScalarType principalPointX, ToFScalarType principalPointY, bool calculateDistance=true); inline static ToFProcessingCommon::ToFPoint3D CartesianToKinectIndexCoordinates(ToFPoint3D cartesianPoint, ToFPoint2D focalLength, ToFPoint2D principalPoint, bool calculateDistance=true) { return CartesianToKinectIndexCoordinates( cartesianPoint[0], cartesianPoint[1], cartesianPoint[2], focalLength[0], focalLength[1], principalPoint[0], principalPoint[1], calculateDistance); } /** @}*/ /** * @brief ContinuousKinectIndexToCartesianCoordinates This method is escpially meant for reconstructing a Kinect point * with continuous index coordinates (i.e. not exactly a pixel position, but a point interpolated between two pixels). * The only difference to KinectIndexToCartesianCoordinates() is that ContinuousKinectIndexToCartesianCoordinates does not * cast to unsigned int for the index. * @param continuousIndex The continuous coordinates (e.g. 0.5; 0.5). * @param distance Distance value d in mm as obtained from OpenNI. * @param focalLengthX x value of the focal length (from calibration). * @param focalLengthY y value of the focal length (from calibration) * @param principalPointX x value of the principal point (from calibration). * @param principalPointY y value of the principal point (from calibration). * @return a ToFPoint3D. The point in world coordinates (mm). */ static ToFProcessingCommon::ToFPoint3D ContinuousKinectIndexToCartesianCoordinates(mitk::Point2D continuousIndex, ToFScalarType distance, ToFScalarType focalLengthX, ToFScalarType focalLengthY, ToFScalarType principalPointX, ToFScalarType principalPointY); }; } #endif diff --git a/Modules/ToFProcessing/mitkToFSurfaceVtkMapper3D.cpp b/Modules/ToFProcessing/mitkToFSurfaceVtkMapper3D.cpp index 15d1ef52a7..8dca206acf 100644 --- a/Modules/ToFProcessing/mitkToFSurfaceVtkMapper3D.cpp +++ b/Modules/ToFProcessing/mitkToFSurfaceVtkMapper3D.cpp @@ -1,506 +1,507 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkToFSurfaceVtkMapper3D.h" #include "mitkDataNode.h" #include "mitkProperties.h" #include "mitkColorProperty.h" #include "mitkLookupTableProperty.h" #include "mitkVtkRepresentationProperty.h" #include "mitkVtkInterpolationProperty.h" #include "mitkVtkScalarModeProperty.h" #include "mitkClippingProperty.h" #include "mitkShaderProperty.h" #include "mitkShaderRepository.h" #include #include #include #include #include #include #include #include #include #include #include //const mitk::ToFSurface* mitk::ToFSurfaceVtkMapper3D::GetInput() const mitk::Surface* mitk::ToFSurfaceVtkMapper3D::GetInput() { //return static_cast ( GetData() ); - return static_cast ( GetData() ); + return static_cast ( GetDataNode()->GetData() ); } mitk::ToFSurfaceVtkMapper3D::ToFSurfaceVtkMapper3D() { // m_Prop3D = vtkActor::New(); m_GenerateNormals = false; this->m_Texture = NULL; this->m_TextureWidth = 0; this->m_TextureHeight = 0; this->m_VtkScalarsToColors = NULL; } mitk::ToFSurfaceVtkMapper3D::~ToFSurfaceVtkMapper3D() { // m_Prop3D->Delete(); } void mitk::ToFSurfaceVtkMapper3D::GenerateDataForRenderer(mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); - bool visible = IsVisible(renderer); + bool visible = true; + GetDataNode()->GetVisibility(visible, renderer, "visible"); - if(visible==false) + if ( !visible ) { ls->m_Actor->VisibilityOff(); return; } // // set the input-object at time t for the mapper // //mitk::ToFSurface::Pointer input = const_cast< mitk::ToFSurface* >( this->GetInput() ); mitk::Surface::Pointer input = const_cast< mitk::Surface* >( this->GetInput() ); vtkPolyData * polydata = input->GetVtkPolyData( this->GetTimestep() ); if(polydata == NULL) { ls->m_Actor->VisibilityOff(); return; } if ( m_GenerateNormals ) { ls->m_VtkPolyDataNormals->SetInput( polydata ); ls->m_VtkPolyDataMapper->SetInput( ls->m_VtkPolyDataNormals->GetOutput() ); } else { ls->m_VtkPolyDataMapper->SetInput( polydata ); } // // apply properties read from the PropertyList // ApplyProperties(ls->m_Actor, renderer); if(visible) ls->m_Actor->VisibilityOn(); // // TOF extension for visualization (color/texture mapping) // if (this->m_VtkScalarsToColors) { // set the color transfer funtion if applied ls->m_VtkPolyDataMapper->SetLookupTable(this->m_VtkScalarsToColors); } if (this->m_Texture) { ls->m_Actor->SetTexture(this->m_Texture); } else { // remove the texture ls->m_Actor->SetTexture(0); } } void mitk::ToFSurfaceVtkMapper3D::ResetMapper( BaseRenderer* renderer ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); ls->m_Actor->VisibilityOff(); } void mitk::ToFSurfaceVtkMapper3D::ApplyMitkPropertiesToVtkProperty(mitk::DataNode *node, vtkProperty* property, mitk::BaseRenderer* renderer) { // Colors { double ambient [3] = { 0.5,0.5,0.0 }; double diffuse [3] = { 0.5,0.5,0.0 }; double specular[3] = { 1.0,1.0,1.0 }; float coeff_ambient = 0.5f; float coeff_diffuse = 0.5f; float coeff_specular= 0.5f; float power_specular=10.0f; // Color { mitk::ColorProperty::Pointer p; node->GetProperty(p, "color", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); ambient[0]=c.GetRed(); ambient[1]=c.GetGreen(); ambient[2]=c.GetBlue(); diffuse[0]=c.GetRed(); diffuse[1]=c.GetGreen(); diffuse[2]=c.GetBlue(); // Setting specular color to the same, make physically no real sense, however vtk rendering slows down, if these colors are different. specular[0]=c.GetRed(); specular[1]=c.GetGreen(); specular[2]=c.GetBlue(); } } // Ambient { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.ambientColor", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); ambient[0]=c.GetRed(); ambient[1]=c.GetGreen(); ambient[2]=c.GetBlue(); } } // Diffuse { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.diffuseColor", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); diffuse[0]=c.GetRed(); diffuse[1]=c.GetGreen(); diffuse[2]=c.GetBlue(); } } // Specular { mitk::ColorProperty::Pointer p; node->GetProperty(p, "material.specularColor", renderer); if(p.IsNotNull()) { mitk::Color c = p->GetColor(); specular[0]=c.GetRed(); specular[1]=c.GetGreen(); specular[2]=c.GetBlue(); } } // Ambient coeff { node->GetFloatProperty("material.ambientCoefficient", coeff_ambient, renderer); } // Diffuse coeff { node->GetFloatProperty("material.diffuseCoefficient", coeff_diffuse, renderer); } // Specular coeff { node->GetFloatProperty("material.specularCoefficient", coeff_specular, renderer); } // Specular power { node->GetFloatProperty("material.specularPower", power_specular, renderer); } property->SetAmbient( coeff_ambient ); property->SetDiffuse( coeff_diffuse ); property->SetSpecular( coeff_specular ); property->SetSpecularPower( power_specular ); property->SetAmbientColor( ambient ); property->SetDiffuseColor( diffuse ); property->SetSpecularColor( specular ); } // Render mode { // Opacity { float opacity = 1.0f; if( node->GetOpacity(opacity,renderer) ) property->SetOpacity( opacity ); } // Wireframe line width { float lineWidth = 1; node->GetFloatProperty("material.wireframeLineWidth", lineWidth, renderer); property->SetLineWidth( lineWidth ); } // Representation { mitk::VtkRepresentationProperty::Pointer p; node->GetProperty(p, "material.representation", renderer); if(p.IsNotNull()) property->SetRepresentation( p->GetVtkRepresentation() ); } // Interpolation { mitk::VtkInterpolationProperty::Pointer p; node->GetProperty(p, "material.interpolation", renderer); if(p.IsNotNull()) property->SetInterpolation( p->GetVtkInterpolation() ); } } } void mitk::ToFSurfaceVtkMapper3D::ApplyProperties(vtkActor* /*actor*/, mitk::BaseRenderer* renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // Applying shading properties { - Superclass::ApplyProperties( ls->m_Actor, renderer ) ; + ApplyColorAndOpacityProperties( renderer, ls->m_Actor ) ; // VTK Properties ApplyMitkPropertiesToVtkProperty( this->GetDataNode(), ls->m_Actor->GetProperty(), renderer ); // Shaders mitk::ShaderRepository::GetGlobalShaderRepository()->ApplyProperties(this->GetDataNode(),ls->m_Actor,renderer,ls->m_ShaderTimestampUpdate); } mitk::LookupTableProperty::Pointer lookupTableProp; this->GetDataNode()->GetProperty(lookupTableProp, "LookupTable", renderer); if (lookupTableProp.IsNotNull() ) { ls->m_VtkPolyDataMapper->SetLookupTable(lookupTableProp->GetLookupTable()->GetVtkLookupTable()); } mitk::LevelWindow levelWindow; if(this->GetDataNode()->GetLevelWindow(levelWindow, renderer, "levelWindow")) { ls->m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetLowerWindowBound(),levelWindow.GetUpperWindowBound()); } else if(this->GetDataNode()->GetLevelWindow(levelWindow, renderer)) { ls->m_VtkPolyDataMapper->SetScalarRange(levelWindow.GetLowerWindowBound(),levelWindow.GetUpperWindowBound()); } bool scalarVisibility = false; this->GetDataNode()->GetBoolProperty("scalar visibility", scalarVisibility); ls->m_VtkPolyDataMapper->SetScalarVisibility( (scalarVisibility ? 1 : 0) ); if(scalarVisibility) { mitk::VtkScalarModeProperty* scalarMode; if(this->GetDataNode()->GetProperty(scalarMode, "scalar mode", renderer)) { ls->m_VtkPolyDataMapper->SetScalarMode(scalarMode->GetVtkScalarMode()); } else ls->m_VtkPolyDataMapper->SetScalarModeToDefault(); bool colorMode = false; this->GetDataNode()->GetBoolProperty("color mode", colorMode); ls->m_VtkPolyDataMapper->SetColorMode( (colorMode ? 1 : 0) ); float scalarsMin = 0; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum")) != NULL) scalarsMin = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum"))->GetValue(); float scalarsMax = 1.0; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum")) != NULL) scalarsMax = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum"))->GetValue(); ls->m_VtkPolyDataMapper->SetScalarRange(scalarsMin,scalarsMax); } // deprecated settings bool deprecatedUseCellData = false; this->GetDataNode()->GetBoolProperty("deprecated useCellDataForColouring", deprecatedUseCellData); bool deprecatedUsePointData = false; this->GetDataNode()->GetBoolProperty("deprecated usePointDataForColouring", deprecatedUsePointData); if (deprecatedUseCellData) { ls->m_VtkPolyDataMapper->SetColorModeToDefault(); ls->m_VtkPolyDataMapper->SetScalarRange(0,255); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_VtkPolyDataMapper->SetScalarModeToUseCellData(); ls->m_Actor->GetProperty()->SetSpecular (1); ls->m_Actor->GetProperty()->SetSpecularPower (50); ls->m_Actor->GetProperty()->SetInterpolationToPhong(); } else if (deprecatedUsePointData) { float scalarsMin = 0; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum")) != NULL) scalarsMin = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMinimum"))->GetValue(); float scalarsMax = 0.1; if (dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum")) != NULL) scalarsMax = dynamic_cast(this->GetDataNode()->GetProperty("ScalarsRangeMaximum"))->GetValue(); ls->m_VtkPolyDataMapper->SetScalarRange(scalarsMin,scalarsMax); ls->m_VtkPolyDataMapper->SetColorModeToMapScalars(); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_Actor->GetProperty()->SetSpecular (1); ls->m_Actor->GetProperty()->SetSpecularPower (50); ls->m_Actor->GetProperty()->SetInterpolationToPhong(); } int deprecatedScalarMode = VTK_COLOR_MODE_DEFAULT; if(this->GetDataNode()->GetIntProperty("deprecated scalar mode", deprecatedScalarMode, renderer)) { ls->m_VtkPolyDataMapper->SetScalarMode(deprecatedScalarMode); ls->m_VtkPolyDataMapper->ScalarVisibilityOn(); ls->m_Actor->GetProperty()->SetSpecular (1); ls->m_Actor->GetProperty()->SetSpecularPower (50); //m_Actor->GetProperty()->SetInterpolationToPhong(); } // Check whether one or more ClippingProperty objects have been defined for // this node. Check both renderer specific and global property lists, since // properties in both should be considered. const PropertyList::PropertyMap *rendererProperties = this->GetDataNode()->GetPropertyList( renderer )->GetMap(); const PropertyList::PropertyMap *globalProperties = this->GetDataNode()->GetPropertyList( NULL )->GetMap(); // Add clipping planes (if any) ls->m_ClippingPlaneCollection->RemoveAllItems(); PropertyList::PropertyMap::const_iterator it; for ( it = rendererProperties->begin(); it != rendererProperties->end(); ++it ) { this->CheckForClippingProperty( renderer,(*it).second.GetPointer() ); } for ( it = globalProperties->begin(); it != globalProperties->end(); ++it ) { this->CheckForClippingProperty( renderer,(*it).second.GetPointer() ); } if ( ls->m_ClippingPlaneCollection->GetNumberOfItems() > 0 ) { ls->m_VtkPolyDataMapper->SetClippingPlanes( ls->m_ClippingPlaneCollection ); } else { ls->m_VtkPolyDataMapper->RemoveAllClippingPlanes(); } } vtkProp *mitk::ToFSurfaceVtkMapper3D::GetVtkProp(mitk::BaseRenderer *renderer) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); return ls->m_Actor; } void mitk::ToFSurfaceVtkMapper3D::CheckForClippingProperty( mitk::BaseRenderer* renderer, mitk::BaseProperty *property ) { LocalStorage *ls = m_LSH.GetLocalStorage(renderer); // m_Prop3D = ls->m_Actor; ClippingProperty *clippingProperty = dynamic_cast< ClippingProperty * >( property ); if ( (clippingProperty != NULL) && (clippingProperty->GetClippingEnabled()) ) { const Point3D &origin = clippingProperty->GetOrigin(); const Vector3D &normal = clippingProperty->GetNormal(); vtkPlane *clippingPlane = vtkPlane::New(); clippingPlane->SetOrigin( origin[0], origin[1], origin[2] ); clippingPlane->SetNormal( normal[0], normal[1], normal[2] ); ls->m_ClippingPlaneCollection->AddItem( clippingPlane ); clippingPlane->UnRegister( NULL ); } } void mitk::ToFSurfaceVtkMapper3D::SetDefaultPropertiesForVtkProperty(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { // Shading { node->AddProperty( "material.wireframeLineWidth", mitk::FloatProperty::New(1.0f) , renderer, overwrite ); node->AddProperty( "material.ambientCoefficient" , mitk::FloatProperty::New(0.05f) , renderer, overwrite ); node->AddProperty( "material.diffuseCoefficient" , mitk::FloatProperty::New(0.9f) , renderer, overwrite ); node->AddProperty( "material.specularCoefficient", mitk::FloatProperty::New(1.0f) , renderer, overwrite ); node->AddProperty( "material.specularPower" , mitk::FloatProperty::New(16.0f) , renderer, overwrite ); //node->AddProperty( "material.ambientColor" , mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); //node->AddProperty( "material.diffuseColor" , mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); //node->AddProperty( "material.specularColor" , mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); node->AddProperty( "material.representation" , mitk::VtkRepresentationProperty::New() , renderer, overwrite ); node->AddProperty( "material.interpolation" , mitk::VtkInterpolationProperty::New() , renderer, overwrite ); } // Shaders { mitk::ShaderRepository::GetGlobalShaderRepository()->AddDefaultProperties(node,renderer,overwrite); } } void mitk::ToFSurfaceVtkMapper3D::SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite) { node->AddProperty( "color", mitk::ColorProperty::New(1.0f,1.0f,1.0f), renderer, overwrite ); node->AddProperty( "opacity", mitk::FloatProperty::New(1.0), renderer, overwrite ); mitk::ToFSurfaceVtkMapper3D::SetDefaultPropertiesForVtkProperty(node,renderer,overwrite); // Shading node->AddProperty( "scalar visibility", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "color mode", mitk::BoolProperty::New(false), renderer, overwrite ); node->AddProperty( "scalar mode", mitk::VtkScalarModeProperty::New(), renderer, overwrite ); mitk::Surface::Pointer surface = dynamic_cast(node->GetData()); if(surface.IsNotNull()) { if((surface->GetVtkPolyData() != 0) && (surface->GetVtkPolyData()->GetPointData() != NULL) && (surface->GetVtkPolyData()->GetPointData()->GetScalars() != 0)) { node->AddProperty( "scalar visibility", mitk::BoolProperty::New(true), renderer, overwrite ); node->AddProperty( "color mode", mitk::BoolProperty::New(true), renderer, overwrite ); } } Superclass::SetDefaultProperties(node, renderer, overwrite); } void mitk::ToFSurfaceVtkMapper3D::SetImmediateModeRenderingOn(int /*on*/) { /* if (m_VtkPolyDataMapper != NULL) m_VtkPolyDataMapper->SetImmediateModeRendering(on); */ } void mitk::ToFSurfaceVtkMapper3D::SetTexture(vtkImageData *img) { this->m_Texture = vtkSmartPointer::New(); this->m_Texture->SetInput(img); // MITK_INFO << "Neuer Code"; } vtkSmartPointer mitk::ToFSurfaceVtkMapper3D::GetTexture() { return this->m_Texture; } void mitk::ToFSurfaceVtkMapper3D::SetVtkScalarsToColors(vtkScalarsToColors* vtkScalarsToColors) { this->m_VtkScalarsToColors = vtkScalarsToColors; } vtkScalarsToColors* mitk::ToFSurfaceVtkMapper3D::GetVtkScalarsToColors() { return this->m_VtkScalarsToColors; } diff --git a/Modules/ToFProcessing/mitkToFSurfaceVtkMapper3D.h b/Modules/ToFProcessing/mitkToFSurfaceVtkMapper3D.h index e237607cd9..960833158f 100644 --- a/Modules/ToFProcessing/mitkToFSurfaceVtkMapper3D.h +++ b/Modules/ToFProcessing/mitkToFSurfaceVtkMapper3D.h @@ -1,186 +1,186 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKTOFSURFACEDATAVTKMAPPER3D_H_HEADER_INCLUDED_C1907273 #define MITKTOFSURFACEDATAVTKMAPPER3D_H_HEADER_INCLUDED_C1907273 #include "mitkCommon.h" -#include "mitkVtkMapper3D.h" +#include "mitkVtkMapper.h" #include "mitkSurface.h" #include "mitkBaseRenderer.h" #include #include #include #include #include #include #include #include #include "mitkToFProcessingExports.h" namespace mitk { //##Documentation //## @brief Vtk-based mapper for Surface //## //## @ingroup Mapper /** * @brief Vtk-based mapper for Surface * * Properties that can be set for surfaces and influence the surfaceVTKMapper3D are: * * - \b "color": (ColorProperty) Diffuse color of the surface object (this property will be read when material.diffuseColor is not defined) * - \b "Opacity": (FloatProperty) Opacity of the surface object * - \b "material.ambientColor": (ColorProperty) Ambient color of the surface object * - \b "material.ambientCoefficient": ( FloatProperty) Ambient coefficient of the surface object * - \b "material.diffuseColor": ( ColorProperty) Diffuse color of the surface object * - \b "material.diffuseCoefficient": (FloatProperty) Diffuse coefficient of the surface object * - \b "material.specularColor": (ColorProperty) Specular Color of the surface object * - \b "material.specularCoefficient": (FloatProperty) Specular coefficient of the surface object * - \b "material.specularPower": (FloatProperty) Specular power of the surface object * - \b "material.interpolation": (VtkInterpolationProperty) Interpolation * - \b "material.representation": (VtkRepresentationProperty*) Representation * - \b "material.wireframeLineWidth": (FloatProperty) Width in pixels of the lines drawn. * - \b "scalar visibility": (BoolProperty) If the scarlars of the surface are visible * Properties to look for are: * * - \b "scalar visibility": if set to on, scalars assigned to the data are shown * Turn this on if using a lookup table. * - \b "ScalarsRangeMinimum": Optional. Can be used to store the scalar min, e.g. * for the level window settings. * - \b "ScalarsRangeMaximum": Optional. See above. * * There might be still some other, deprecated properties. These will not be documented anymore. * Please check the source if you really need them. * * @ingroup Mapper */ -class mitkToFProcessing_EXPORT ToFSurfaceVtkMapper3D : public VtkMapper3D +class mitkToFProcessing_EXPORT ToFSurfaceVtkMapper3D : public VtkMapper { public: - mitkClassMacro(ToFSurfaceVtkMapper3D, VtkMapper3D); + mitkClassMacro(ToFSurfaceVtkMapper3D, VtkMapper); itkNewMacro(Self); itkSetMacro(GenerateNormals, bool); itkGetMacro(GenerateNormals, bool); //enable ImmediateModeRendering for vtkMapping //yet to solve bug 1398 void SetImmediateModeRenderingOn(int on = 1); itkGetMacro(ImmediateModeRenderingOn, int); //virtual const mitk::ToFSurface* GetInput(); virtual const mitk::Surface* GetInput(); virtual vtkProp *GetVtkProp(mitk::BaseRenderer *renderer); virtual void ApplyProperties(vtkActor* actor, mitk::BaseRenderer* renderer); static void SetDefaultProperties(mitk::DataNode* node, mitk::BaseRenderer* renderer = NULL, bool overwrite = false); void SetTexture(vtkImageData *img); vtkSmartPointer GetTexture(); itkSetMacro(TextureWidth, int); itkSetMacro(TextureHeight, int); void SetVtkScalarsToColors(vtkScalarsToColors* vtkScalarsToColors); vtkScalarsToColors* GetVtkScalarsToColors(); protected: ToFSurfaceVtkMapper3D(); virtual ~ToFSurfaceVtkMapper3D(); virtual void GenerateDataForRenderer(mitk::BaseRenderer* renderer); virtual void ResetMapper( mitk::BaseRenderer* renderer ); /** Checks whether the specified property is a ClippingProperty and if yes, * adds it to m_ClippingPlaneCollection (internal method). */ virtual void CheckForClippingProperty( mitk::BaseRenderer* renderer, mitk::BaseProperty *property ); bool m_GenerateNormals; //enable ImmediateModeRendering for the vtkMapper int m_ImmediateModeRenderingOn; vtkSmartPointer m_Texture; // pointer to the texture/video image int m_TextureWidth; // width of the texture/video image int m_TextureHeight; // height of the texture/video image vtkScalarsToColors* m_VtkScalarsToColors; // vtk color transfer funtion public: class LocalStorage : public mitk::Mapper::BaseLocalStorage { public: vtkActor* m_Actor; vtkPolyDataMapper *m_VtkPolyDataMapper; vtkPolyDataNormals *m_VtkPolyDataNormals; vtkPlaneCollection *m_ClippingPlaneCollection; itk::TimeStamp m_ShaderTimestampUpdate; LocalStorage() { m_VtkPolyDataMapper = vtkOpenGLPolyDataMapper::New(); m_VtkPolyDataNormals = vtkPolyDataNormals::New(); m_Actor = vtkActor::New(); m_ClippingPlaneCollection = vtkPlaneCollection::New(); m_Actor->SetMapper(m_VtkPolyDataMapper); } ~LocalStorage() { m_VtkPolyDataMapper->Delete(); m_VtkPolyDataNormals->Delete(); m_Actor->Delete(); m_ClippingPlaneCollection->Delete(); } }; mitk::Mapper::LocalStorageHandler m_LSH; static void ApplyMitkPropertiesToVtkProperty(mitk::DataNode *node, vtkProperty* property, mitk::BaseRenderer* renderer); static void SetDefaultPropertiesForVtkProperty(mitk::DataNode* node, mitk::BaseRenderer* renderer, bool overwrite); }; } // namespace mitk #endif /* MITKTOFSURFACEDATAVTKMAPPER3D_H_HEADER_INCLUDED_C1907273 */ diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index 4aae5293f3..2aaa7a7689 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,47 +1,46 @@ # Plug-ins must be ordered according to their dependencies set(MITK_EXT_PLUGINS org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.diffusionimaging:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.dtiatlasapp:OFF org.mitk.gui.qt.examples:OFF org.mitk.gui.qt.examplesopencv:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.meshdecimation:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.python.console:OFF org.mitk.gui.qt.registration:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.simulation:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF - org.mitk.gui.InteractionTests:OFF ) diff --git a/Plugins/org.mitk.core.services/documentation/doxygen/modules.dox b/Plugins/org.mitk.core.services/documentation/doxygen/modules.dox index 9ce368e6d1..d02dced52f 100755 --- a/Plugins/org.mitk.core.services/documentation/doxygen/modules.dox +++ b/Plugins/org.mitk.core.services/documentation/doxygen/modules.dox @@ -1,16 +1,25 @@ /** \defgroup org_mitk_core_services org.mitk.core.services \ingroup MITKPlugins \brief Provides basic MITK services. - + + This plug-in provides service interfaces and service objects for accessing a mitk::DataStorage + via the CTK Plugin Framework service registry. + + It also handles the following tasks: + + - Initialize the MITK Logging back-ends. + - Register adaptor services in the CTK Plugin Framework service registry for each MITK Micro Service. + This allows a seamless access of MITK Micro Service objects from the CTK Plugin Context. + */ /** \defgroup org_mitk_core_services_internal Internal \ingroup org_mitk_core_services \brief This subcategory includes the internal classes of the org.mitk.core.services plugin. Other plugins must not rely on these classes. They contain implementation details and their interface may change at any time. We mean it. */ diff --git a/Plugins/org.mitk.gui.InteractionTests/Resources/PointsConfigRightClick.xml b/Plugins/org.mitk.gui.InteractionTests/Resources/PointsConfigRightClick.xml deleted file mode 100644 index a8684eef4a..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/Resources/PointsConfigRightClick.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/Plugins/org.mitk.gui.InteractionTests/documentation/UserManual/Manual.dox b/Plugins/org.mitk.gui.InteractionTests/documentation/UserManual/Manual.dox deleted file mode 100644 index abdf834276..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/documentation/UserManual/Manual.dox +++ /dev/null @@ -1,18 +0,0 @@ -/** -\page org_mitk_gui_InteractionTests InteractionTests - -\image html icon.xpm "Icon of InteractionTests" - -Available sections: - - \ref org_mitk_gui_InteractionTestsOverview - -\section org_mitk_gui_InteractionTestsOverview -Describe the features of your awesome plugin here -
    -
  • Increases productivity -
  • Creates beautiful images -
  • Generates PhD thesis -
  • Brings world peace -
- -*/ \ No newline at end of file diff --git a/Plugins/org.mitk.gui.InteractionTests/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.InteractionTests/documentation/doxygen/modules.dox deleted file mode 100644 index abdd614931..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/documentation/doxygen/modules.dox +++ /dev/null @@ -1,16 +0,0 @@ -/** - \defgroup org_mitk_gui_InteractionTests org.mitk.gui.InteractionTests - \ingroup MITKPlugins - - \brief Describe your plugin here. - -*/ - -/** - \defgroup org_mitk_gui_InteractionTests_internal Internal - \ingroup org_mitk_gui_InteractionTests - - \brief This subcategory includes the internal classes of the org.mitk.gui.InteractionTests plugin. Other - plugins must not rely on these classes. They contain implementation details and their interface - may change at any time. We mean it. -*/ diff --git a/Plugins/org.mitk.gui.InteractionTests/resources/icon.xpm b/Plugins/org.mitk.gui.InteractionTests/resources/icon.xpm deleted file mode 100644 index 9057c20bc6..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/resources/icon.xpm +++ /dev/null @@ -1,21 +0,0 @@ -/* XPM */ -static const char * icon_xpm[] = { -"16 16 2 1", -" c #FF0000", -". c #000000", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" ", -" "}; diff --git a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.cpp b/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.cpp deleted file mode 100644 index ce3178be7b..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/*=================================================================== - - The Medical Imaging Interaction Toolkit (MITK) - - Copyright (c) German Cancer Research Center, - Division of Medical and Biological Informatics. - All rights reserved. - - This software is distributed WITHOUT ANY WARRANTY; without - even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. - - See LICENSE.txt or http://www.mitk.org for details. - - ===================================================================*/ - -// Blueberry -#include -#include - -// Qmitk -#include "InteractionTests.h" - -// Qt -#include - -// rest - -#include "mitkDataNode.h" -#include - -// us -#include "mitkGetModuleContext.h" -#include "mitkModule.h" -#include "mitkModuleRegistry.h" -#include "mitkInformer.h" - -#include "mitkEventObserver.h" - -//#include "mitkInformerActivator.h" - -const std::string InteractionTests::VIEW_ID = "org.mitk.views.interactiontests"; - -void InteractionTests::SetFocus() -{ - m_Controls.buttonPerformImageProcessing->setFocus(); -} - -void InteractionTests::CreateQtPartControl(QWidget *parent) -{ - // create GUI widgets from the Qt Designer's .ui file - m_Controls.setupUi(parent); - connect(m_Controls.buttonPerformImageProcessing, SIGNAL(clicked()), this, SLOT(DrawLines())); - connect(m_Controls.toggleConfig, SIGNAL(clicked()), this, SLOT(ToggleConfig())); - connect(m_Controls.grabInput, SIGNAL(clicked()), this, SLOT(GrabInput())); - m_Controls.buttonPerformImageProcessing->setText(QString("Line Interactor (Left Click)")); - m_ConfigChoice = true; -} - -void InteractionTests::ToggleConfig() -{ - std::vector selections = GetDataManagerSelection(); - for (std::vector::iterator it = selections.begin(); it != selections.end(); ++it) - { - if ((*it)->GetDataInteractor().IsNotNull()) - { - if (!m_ConfigChoice) - { - (*it)->GetDataInteractor()->LoadEventConfig("globalConfig.xml"); - (*it)->GetDataInteractor()->AddEventConfig("PointSetConfig.xml"); - m_Controls.buttonPerformImageProcessing->setText(QString("Line Interactor (Left Click)")); - m_ConfigChoice = true; - } - else - { - (*it)->GetDataInteractor()->LoadEventConfig("globalConfig.xml"); - (*it)->GetDataInteractor()->AddEventConfig("PointSetConfig.xml"); - m_Controls.buttonPerformImageProcessing->setText(QString("Line Interactor (Right Click)")); - m_ConfigChoice = false; - } - } - } -} - -void InteractionTests::GrabInput() -{ -// m_CurrentDataNode = mitk::DataNode::New(); -// GetDataStorage()->Add(m_CurrentDataNode.GetPointer(), m_CurrentImage); -// -// m_CurrentInteractor = mitk::PointSetDataInteractor::New(); -// if (!m_CurrentInteractor->LoadStateMachine("/home.local/webechr.local/EclipseTest/test/LineSMGrab.xml")) -// { -// return; -// } -// m_CurrentInteractor->LoadEventConfig("/home.local/webechr.local/EclipseTest/test/PointsConfig.xml"); -// m_CurrentInteractor->AddEventConfig("/home.local/webechr.local/EclipseTest/test/globalConfig.xml"); -// m_CurrentInteractor->SetDataNode(m_CurrentDataNode); -} - -void InteractionTests::OnSelectionChanged(berry::IWorkbenchPart::Pointer /*source*/, const QList& nodes) -{ - // iterate all selected objects, adjust warning visibility - foreach ( mitk::DataNode::Pointer node, nodes ){ - if( node.IsNotNull() && dynamic_cast(node->GetData()) ) - { - m_CurrentImage = node; - m_Controls.labelWarning->setVisible( false ); - m_Controls.buttonPerformImageProcessing->setEnabled( true ); - return; - } -} -m_Controls.labelWarning->setVisible( true ); -m_Controls.buttonPerformImageProcessing->setEnabled( false ); -} - -void InteractionTests::DrawLines() -{ - m_CurrentDataNode = mitk::DataNode::New(); - GetDataStorage()->Add(m_CurrentDataNode.GetPointer(), m_CurrentImage); - //m_CurrentInteractor = mitk::TestInteractor::New(); - m_CurrentInteractor = mitk::PointSetDataInteractor::New(); - m_CurrentInteractor->LoadStateMachine("PointSet.xml"); - - if (m_ConfigChoice) - { - m_CurrentInteractor->LoadEventConfig("globalConfig.xml"); - m_CurrentInteractor->AddEventConfig("PointSetConfig.xml"); - } - else - { - m_CurrentInteractor->LoadEventConfig("globalConfig.xml"); - m_CurrentInteractor->AddEventConfig("PointSetConfig.xml"); - } - m_CurrentInteractor->SetDataNode(m_CurrentDataNode); - - mitk::EventObserver::Pointer eO = mitk::EventObserver::New(); - mitk::ModuleContext* context = mitk::ModuleRegistry::GetModule(1)->GetModuleContext(); - mitk::ServiceReference serviceRef = context->GetServiceReference(); - mitk::InformerService* service = dynamic_cast(context->GetService(serviceRef)); - service->RegisterObserver(eO); - -} diff --git a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.h b/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.h deleted file mode 100644 index 9125363275..0000000000 --- a/Plugins/org.mitk.gui.InteractionTests/src/internal/InteractionTests.h +++ /dev/null @@ -1,70 +0,0 @@ -/*=================================================================== - - The Medical Imaging Interaction Toolkit (MITK) - - Copyright (c) German Cancer Research Center, - Division of Medical and Biological Informatics. - All rights reserved. - - This software is distributed WITHOUT ANY WARRANTY; without - even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. - - See LICENSE.txt or http://www.mitk.org for details. - - ===================================================================*/ - -#ifndef InteractionTests_h -#define InteractionTests_h - -#include - -#include - -#include "mitkPointSetDataInteractor.h" - -#include "ui_InteractionTestsControls.h" - -/*! - \brief InteractionTests - - \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. - - \sa QmitkFunctionality - \ingroup ${plugin_target}_internal - */ -class InteractionTests: public QmitkFunctionality -{ - // this is needed for all Qt objects that should have a Qt meta-object - // (everything that derives from QObject and wants to have signal/slots) -Q_OBJECT - -public: - - static const std::string VIEW_ID; - - virtual void CreateQtPartControl(QWidget *parent); - -protected slots: - - /// \brief Called when the user clicks the GUI button - void DrawLines(); - void ToggleConfig(); - void GrabInput(); - -protected: - - virtual void SetFocus(); - - /// \brief called by QmitkFunctionality when DataManager's selection has changed - virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer source, const QList& nodes); - - Ui::InteractionTestsControls m_Controls; -private: - mitk::DataNode::Pointer m_CurrentDataNode; - mitk::PointSetDataInteractor::Pointer m_CurrentInteractor; - mitk::DataNode::Pointer m_CurrentImage; - bool m_ConfigChoice; -}; - -#endif // InteractionTests_h diff --git a/Plugins/org.mitk.gui.common/src/mitkIRenderWindowPart.h b/Plugins/org.mitk.gui.common/src/mitkIRenderWindowPart.h index 03cf2f2182..0c94464f52 100644 --- a/Plugins/org.mitk.gui.common/src/mitkIRenderWindowPart.h +++ b/Plugins/org.mitk.gui.common/src/mitkIRenderWindowPart.h @@ -1,230 +1,230 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKIRENDERWINDOWPART_H #define MITKIRENDERWINDOWPART_H #include #include #include #include #include #include #include class QmitkRenderWindow; namespace mitk { struct IRenderingManager; class SliceNavigationController; /** * \ingroup org_mitk_gui_common * * \brief Interface for a MITK Workbench Part providing a render window. * * This interface allows generic access to Workbench parts which provide some * kind of render window. The interface is intended to be implemented by * subclasses of berry::IWorkbenchPart. Usually, the interface is implemented * by a Workbench editor. * * A IRenderWindowPart provides zero or more QmitkRenderWindow instances which can * be controlled via this interface. QmitkRenderWindow instances have an associated * \e id, which is implementation specific. However, implementations should consider * to use one of the following ids for certain QmitkRenderWindow instances to maximize * reusability (they are free to map multiple ids to one QmitkRenderWindow internally): *
    *
  • transversal (deprecated, use axial instead)
  • *
  • axial
  • *
  • sagittal
  • *
  • coronal
  • *
  • 3d
  • *
* * \see ILinkedRenderWindowPart * \see IRenderWindowPartListener * \see QmitkAbstractRenderEditor */ struct MITK_GUI_COMMON_PLUGIN IRenderWindowPart { static const QString DECORATION_BORDER; // = "border" static const QString DECORATION_LOGO; // = "logo" static const QString DECORATION_MENU; // = "menu" static const QString DECORATION_BACKGROUND; // = "background; virtual ~IRenderWindowPart(); /** * Get the currently active (focused) render window. * Focus handling is implementation specific. * * \return The active QmitkRenderWindow instance; NULL * if no render window is active. * - * \deprecated The method is deprecated, use the IRenderWindowPart::GetActiveQmitkRenderWindow() instead + * \deprecatedSince{2012_09} The method is deprecated, use the IRenderWindowPart::GetActiveQmitkRenderWindow() instead */ DEPRECATED( virtual QmitkRenderWindow* GetActiveRenderWindow() const) { return GetActiveQmitkRenderWindow(); } /** * Get all render windows with their ids. * * \return A hash map mapping the render window id to the QmitkRenderWindow instance. * - * \deprecated The method is deprecated, use the IRenderWindowPart::GetQmitkRenderWindows() instead + * \deprecatedSince{2012_09} The method is deprecated, use the IRenderWindowPart::GetQmitkRenderWindows() instead */ DEPRECATED( virtual QHash GetRenderWindows() const ) { return GetQmitkRenderWindows(); } /** * Get a render window with a specific id. * * \param id The render window id. * \return The QmitkRenderWindow instance for id * - * \deprecated The method is deprecated, use the IRenderWindowPart::GetQmitkRenderWindow(const QString& id) instead + * \deprecatedSince{2012_09} The method is deprecated, use the IRenderWindowPart::GetQmitkRenderWindow(const QString& id) instead */ DEPRECATED( virtual QmitkRenderWindow* GetRenderWindow(const QString& id) const ) { return GetQmitkRenderWindow( id ); } /** * Get the currently active (focused) render window. * Focus handling is implementation specific. * * \return The active QmitkRenderWindow instance; NULL * if no render window is active. */ virtual QmitkRenderWindow* GetActiveQmitkRenderWindow() const = 0; /** * Get all render windows with their ids. * * \return A hash map mapping the render window id to the QmitkRenderWindow instance. */ virtual QHash GetQmitkRenderWindows() const = 0; /** * Get a render window with a specific id. * * \param id The render window id. * \return The QmitkRenderWindow instance for id */ virtual QmitkRenderWindow* GetQmitkRenderWindow(const QString& id) const = 0; /** * Get the rendering manager used by this render window part. * * \return The current IRenderingManager instance or NULL * if no rendering manager is used. */ virtual mitk::IRenderingManager* GetRenderingManager() const = 0; /** * Request an update of all render windows. * * \param requestType Specifies the type of render windows for which an update * will be requested. */ virtual void RequestUpdate(mitk::RenderingManager::RequestType requestType = mitk::RenderingManager::REQUEST_UPDATE_ALL) = 0; /** * Force an immediate update of all render windows. * * \param requestType Specifies the type of render windows for which an immediate update * will be requested. */ virtual void ForceImmediateUpdate(mitk::RenderingManager::RequestType requestType = mitk::RenderingManager::REQUEST_UPDATE_ALL) = 0; /** * Get the SliceNavigationController for controlling time positions. * * \return A SliceNavigationController if the render window supports this * operation; otherwise returns NULL. */ virtual mitk::SliceNavigationController* GetTimeNavigationController() const = 0; /** * Get the selected position in the render window with id id * or in the active render window if id is NULL. * * \param id The render window id. * \return The currently selected position in world coordinates. */ virtual mitk::Point3D GetSelectedPosition(const QString& id = QString()) const = 0; /** * Set the selected position in the render window with id id * or in the active render window if id is NULL. * * \param pos The position in world coordinates which should be selected. * \param id The render window id in which the selection should take place. */ virtual void SetSelectedPosition(const mitk::Point3D& pos, const QString& id = QString()) = 0; /** * Enable \e decorations like colored borders, menu widgets, logos, text annotations, etc. * * Decorations are implementation specific. A set of standardized decoration names is listed * in GetDecorations(). * * \param enable If true enable the decorations specified in decorations, * otherwise disable them. * \param decorations A list of decoration names. If empty, all supported decorations are affected. * * \see GetDecorations() */ virtual void EnableDecorations(bool enable, const QStringList& decorations = QStringList()) = 0; /** * Return if a specific decoration is enabled. * * \return true if the decoration is enabled, false if it is disabled * or unknown. * * \see GetDecorations() */ virtual bool IsDecorationEnabled(const QString& decoration) const = 0; /** * Get a list of supported decorations. * * The following decoration names are standardized and should not be used for other decoration types: *
    *
  • \e DECORATION_BORDER Any border decorations like colored rectangles, etc. *
  • \e DECORATION_MENU Menus associated with render windows *
  • \e DECORATION_BACKGROUND All kinds of backgrounds (patterns, gradients, etc.) except for solid colored backgrounds *
  • \e DECORATION_LOGO Any kind of logo overlayed on the rendered scene *
* * \return A list of supported decoration names. */ virtual QStringList GetDecorations() const = 0; }; } Q_DECLARE_INTERFACE(mitk::IRenderWindowPart, "org.mitk.ui.IRenderWindowPart") #endif // MITKIRENDERWINDOWPART_H diff --git a/Plugins/org.mitk.gui.qt.application/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.application/documentation/doxygen/modules.dox index 77592d99d4..c89ec4876f 100755 --- a/Plugins/org.mitk.gui.qt.application/documentation/doxygen/modules.dox +++ b/Plugins/org.mitk.gui.qt.application/documentation/doxygen/modules.dox @@ -1,16 +1,23 @@ /** \defgroup org_mitk_gui_qt_application org.mitk.gui.qt.application \ingroup MITKPlugins \brief Provides utility classes for MITK application developers. - + + This plug-in provides QAction derived classes for common application actions + like opening files and closing the application. It also provides a central + preferences dialog. + + The plug-in is usually used as a dependency for plug-ins contributing a + \ref xp_org_blueberry_osgi_applications extension and providing workbench advisor + classes which customize the main application menu and toolbar. */ /** \defgroup org_mitk_gui_qt_application_internal Internal \ingroup org_mitk_gui_qt_application \brief This subcategory includes the internal classes of the org.mitk.gui.qt.application plugin. Other plugins must not rely on these classes. They contain implementation details and their interface may change at any time. We mean it. */ diff --git a/Plugins/org.mitk.gui.qt.application/resources/StateMachine.xml.orig b/Plugins/org.mitk.gui.qt.application/resources/StateMachine.xml.orig deleted file mode 100644 index 1392fa4f37..0000000000 --- a/Plugins/org.mitk.gui.qt.application/resources/StateMachine.xml.orig +++ /dev/null @@ -1,3942 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -<<<<<<< HEAD - -======= - - - ->>>>>>> bug-11950-RedesignMeasurementToolBox - - - - - -<<<<<<< HEAD - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -======= - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->>>>>>> bug-11950-RedesignMeasurementToolBox - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -<<<<<<< HEAD - -======= - ->>>>>>> bug-11950-RedesignMeasurementToolBox - - - - - - -<<<<<<< HEAD - - - - - -======= -
- - - - ->>>>>>> bug-11950-RedesignMeasurementToolBox - - - - - - - - - - - - - - -<<<<<<< HEAD - -======= - ->>>>>>> bug-11950-RedesignMeasurementToolBox - - - - - -<<<<<<< HEAD - - - - - - -======= - - - - - - ->>>>>>> bug-11950-RedesignMeasurementToolBox - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Plugins/org.mitk.gui.qt.common/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.common/documentation/doxygen/modules.dox index a9b4ee94e6..f38f873772 100755 --- a/Plugins/org.mitk.gui.qt.common/documentation/doxygen/modules.dox +++ b/Plugins/org.mitk.gui.qt.common/documentation/doxygen/modules.dox @@ -1,16 +1,23 @@ /** \defgroup org_mitk_gui_qt_common org.mitk.gui.qt.common \ingroup MITKPlugins \brief Provides Qt GUI specific utility classes for MITK View and Editor developers. - + + This plug-in provides abstract classes to ease the development of MITK related View and + Editor extensions for a BlueBerry based application. The main classes are: + + - QmitkAbstractView + - QmitkAbstractRenderEditor + + See also the GUI toolkit independent classes and interfaces in \ref org_mitk_gui_common. */ /** \defgroup org_mitk_gui_qt_common_internal Internal \ingroup org_mitk_gui_qt_common \brief This subcategory includes the internal classes of the org.mitk.gui.qt.common plugin. Other plugins must not rely on these classes. They contain implementation details and their interface may change at any time. We mean it. */ diff --git a/Plugins/org.mitk.gui.qt.coreapplication/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.coreapplication/documentation/doxygen/modules.dox index 3d641f9119..44df878ed5 100755 --- a/Plugins/org.mitk.gui.qt.coreapplication/documentation/doxygen/modules.dox +++ b/Plugins/org.mitk.gui.qt.coreapplication/documentation/doxygen/modules.dox @@ -1,16 +1,17 @@ /** \defgroup org_mitk_gui_qt_coreapplication org.mitk.gui.qt.coreapplication \ingroup MITKPlugins \brief The CoreApp applictaion plug-in. + Creates the menu and toolbar entries for the main application window. */ /** \defgroup org_mitk_gui_qt_coreapplication_internal Internal \ingroup org_mitk_gui_qt_coreapplication \brief This subcategory includes the internal classes of the org.mitk.gui.qt.coreapplication plugin. Other plugins must not rely on these classes. They contain implementation details and their interface may change at any time. We mean it. */ diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp index ac69ba56e4..8100f533a3 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.cpp @@ -1,1328 +1,1312 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //misc #define _USE_MATH_DEFINES #include // Blueberry #include #include // Qmitk #include "QmitkFiberfoxView.h" // MITK #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 #define _USE_MATH_DEFINES #include const std::string QmitkFiberfoxView::VIEW_ID = "org.mitk.views.fiberfoxview"; QmitkFiberfoxView::QmitkFiberfoxView() : QmitkAbstractView() , m_Controls( 0 ) , m_SelectedImage( NULL ) , m_SelectedBundle( NULL ) { } // Destructor QmitkFiberfoxView::~QmitkFiberfoxView() { } void QmitkFiberfoxView::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::QmitkFiberfoxViewControls; m_Controls->setupUi( parent ); m_Controls->m_VarianceBox->setVisible(false); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_T2bluringParamFrame->setVisible(false); m_Controls->m_KspaceParamFrame->setVisible(false); m_Controls->m_StickModelFrame->setVisible(false); m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); + m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); connect((QObject*) m_Controls->m_GenerateImageButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateImage())); connect((QObject*) m_Controls->m_GenerateFibersButton, SIGNAL(clicked()), (QObject*) this, SLOT(GenerateFibers())); connect((QObject*) m_Controls->m_CircleButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnDrawROI())); connect((QObject*) m_Controls->m_FlipButton, SIGNAL(clicked()), (QObject*) this, SLOT(OnFlipButton())); connect((QObject*) m_Controls->m_JoinBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(JoinBundles())); connect((QObject*) m_Controls->m_VarianceBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnVarianceChanged(double))); connect((QObject*) m_Controls->m_DistributionBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(OnDistributionChanged(int))); connect((QObject*) m_Controls->m_FiberDensityBox, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(OnFiberDensityChanged(int))); connect((QObject*) m_Controls->m_FiberSamplingBox, SIGNAL(valueChanged(int)), (QObject*) this, SLOT(OnFiberSamplingChanged(int))); connect((QObject*) m_Controls->m_TensionBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnTensionChanged(double))); connect((QObject*) m_Controls->m_ContinuityBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnContinuityChanged(double))); connect((QObject*) m_Controls->m_BiasBox, SIGNAL(valueChanged(double)), (QObject*) this, SLOT(OnBiasChanged(double))); - connect((QObject*) m_Controls->m_AddT2Smearing, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddT2Smearing(int))); connect((QObject*) m_Controls->m_AddGibbsRinging, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnAddGibbsRinging(int))); connect((QObject*) m_Controls->m_ConstantRadiusBox, SIGNAL(stateChanged(int)), (QObject*) this, SLOT(OnConstantRadius(int))); connect((QObject*) m_Controls->m_CopyBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(CopyBundles())); connect((QObject*) m_Controls->m_TransformBundlesButton, SIGNAL(clicked()), (QObject*) this, SLOT(ApplyTransform())); connect((QObject*) m_Controls->m_AlignOnGrid, SIGNAL(clicked()), (QObject*) this, SLOT(AlignOnGrid())); connect((QObject*) m_Controls->m_FiberCompartmentModelBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(FiberModelFrameVisibility(int))); connect((QObject*) m_Controls->m_NonFiberCompartmentModelBox, SIGNAL(currentIndexChanged(int)), (QObject*) this, SLOT(FiberModelFrameVisibility(int))); - connect((QObject*) m_Controls->m_AdvancedFiberOptionsBox, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedFiberOptions(int))); + connect((QObject*) m_Controls->m_AdvancedOptionsBox, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); + connect((QObject*) m_Controls->m_AdvancedOptionsBox_2, SIGNAL( stateChanged(int)), (QObject*) this, SLOT(ShowAdvancedOptions(int))); } } -void QmitkFiberfoxView::ShowAdvancedFiberOptions(int state) +void QmitkFiberfoxView::ShowAdvancedOptions(int state) { if (state) + { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(true); + m_Controls->m_AdvancedSignalOptionsFrame->setVisible(true); + } else + { m_Controls->m_AdvancedFiberOptionsFrame->setVisible(false); + m_Controls->m_AdvancedSignalOptionsFrame->setVisible(false); + } } void QmitkFiberfoxView::FiberModelFrameVisibility(int index) { m_Controls->m_TensorModelFrame->setVisible(false); m_Controls->m_StickModelFrame->setVisible(false); switch (index) { case 0: m_Controls->m_TensorModelFrame->setVisible(true); break; case 1: m_Controls->m_StickModelFrame->setVisible(true); break; default: m_Controls->m_TensorModelFrame->setVisible(true); } } void QmitkFiberfoxView::NonFiberModelFrameVisibility(int index) { } void QmitkFiberfoxView::OnConstantRadius(int value) { if (value>0 && m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } -void QmitkFiberfoxView::OnAddT2Smearing(int value) -{ - if (value>0) - m_Controls->m_T2bluringParamFrame->setVisible(true); - else - m_Controls->m_T2bluringParamFrame->setVisible(false); -} - void QmitkFiberfoxView::OnAddGibbsRinging(int value) { if (value>0) m_Controls->m_KspaceParamFrame->setVisible(true); else m_Controls->m_KspaceParamFrame->setVisible(false); } void QmitkFiberfoxView::OnDistributionChanged(int value) { if (value==1) m_Controls->m_VarianceBox->setVisible(true); else m_Controls->m_VarianceBox->setVisible(false); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnVarianceChanged(double value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberDensityChanged(int value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFiberSamplingChanged(int value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnTensionChanged(double value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnContinuityChanged(double value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnBiasChanged(double value) { if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::AlignOnGrid() { for (int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::DataStorage::SetOfObjects::ConstPointer parentFibs = GetDataStorage()->GetSources(m_SelectedFiducials.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = parentFibs->begin(); it != parentFibs->end(); ++it ) { mitk::DataNode::Pointer pFibNode = *it; if ( pFibNode.IsNotNull() && dynamic_cast(pFibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(pFibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { mitk::Image::Pointer img = dynamic_cast(pImgNode->GetData()); mitk::Geometry3D::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); break; } } break; } } } for( int i=0; iGetSources(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it = sources->begin(); it != sources->end(); ++it ) { mitk::DataNode::Pointer imgNode = *it; if ( imgNode.IsNotNull() && dynamic_cast(imgNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::Image::Pointer img = dynamic_cast(imgNode->GetData()); mitk::Geometry3D::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } break; } } } for( int i=0; i(m_SelectedImages.at(i)->GetData()); mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) { mitk::DataStorage::SetOfObjects::ConstPointer derivations2 = GetDataStorage()->GetDerivations(fibNode); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations2->begin(); it2 != derivations2->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = dynamic_cast(fiducialNode->GetData()); mitk::Point3D wc0 = pe->GetWorldControlPoint(0); mitk::Geometry3D::Pointer geom = img->GetGeometry(); itk::Index<3> idx; geom->WorldToIndex(wc0, idx); mitk::Point3D cIdx; cIdx[0]=idx[0]; cIdx[1]=idx[1]; cIdx[2]=idx[2]; mitk::Point3D world; geom->IndexToWorld(cIdx,world); mitk::Vector3D trans = world - wc0; pe->GetGeometry()->Translate(trans); } } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::OnFlipButton() { if (m_SelectedFiducial.IsNull()) return; std::map::iterator it = m_DataNodeToPlanarFigureData.find(m_SelectedFiducial.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; data.m_Flipped += 1; data.m_Flipped %= 2; } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } QmitkFiberfoxView::GradientListType QmitkFiberfoxView::GenerateHalfShell(int NPoints) { NPoints *= 2; GradientListType pointshell; int numB0 = NPoints/10; if (numB0==0) numB0=1; GradientType g; g.Fill(0.0); for (int i=0; i theta; theta.set_size(NPoints); vnl_vector phi; phi.set_size(NPoints); double C = sqrt(4*M_PI); phi(0) = 0.0; phi(NPoints-1) = 0.0; for(int i=0; i0 && i std::vector > QmitkFiberfoxView::MakeGradientList() { std::vector > retval; vnl_matrix_fixed* U = itk::PointShell >::DistributePointShell(); // Add 0 vector for B0 int numB0 = ndirs/10; if (numB0==0) numB0=1; itk::Vector v; v.Fill(0.0); for (int i=0; i v; v[0] = U->get(0,i); v[1] = U->get(1,i); v[2] = U->get(2,i); retval.push_back(v); } return retval; } void QmitkFiberfoxView::OnAddBundle() { if (m_SelectedImage.IsNull()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedImage); mitk::FiberBundleX::Pointer bundle = mitk::FiberBundleX::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( bundle ); QString name = QString("Bundle_%1").arg(children->size()); node->SetName(name.toStdString()); m_SelectedBundle = node; m_SelectedBundles.push_back(node); UpdateGui(); GetDataStorage()->Add(node, m_SelectedImage); } void QmitkFiberfoxView::OnDrawROI() { if (m_SelectedBundle.IsNull()) OnAddBundle(); if (m_SelectedBundle.IsNull()) return; mitk::DataStorage::SetOfObjects::ConstPointer children = GetDataStorage()->GetDerivations(m_SelectedBundle); mitk::PlanarEllipse::Pointer figure = mitk::PlanarEllipse::New(); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( figure ); QList nodes = this->GetDataManagerSelection(); for( int i=0; iSetSelected(false); m_SelectedFiducial = node; QString name = QString("Fiducial_%1").arg(children->size()); node->SetName(name.toStdString()); node->SetSelected(true); GetDataStorage()->Add(node, m_SelectedBundle); this->DisableCrosshairNavigation(); mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetInteractor()); if(figureInteractor.IsNull()) figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", node); mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); UpdateGui(); } bool CompareLayer(mitk::DataNode::Pointer i,mitk::DataNode::Pointer j) { int li = -1; i->GetPropertyValue("layer", li); int lj = -1; j->GetPropertyValue("layer", lj); return liGetSources(m_SelectedFiducial); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) if(dynamic_cast((*it)->GetData())) m_SelectedBundles.push_back(*it); if (m_SelectedBundles.empty()) return; } vector< vector< mitk::PlanarEllipse::Pointer > > fiducials; vector< vector< unsigned int > > fliplist; for (int i=0; iGetDerivations(m_SelectedBundles.at(i)); std::vector< mitk::DataNode::Pointer > childVector; for( mitk::DataStorage::SetOfObjects::const_iterator it = children->begin(); it != children->end(); ++it ) childVector.push_back(*it); sort(childVector.begin(), childVector.end(), CompareLayer); vector< mitk::PlanarEllipse::Pointer > fib; vector< unsigned int > flip; float radius = 1; int count = 0; for( std::vector< mitk::DataNode::Pointer >::const_iterator it = childVector.begin(); it != childVector.end(); ++it ) { mitk::DataNode::Pointer node = *it; if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { mitk::PlanarEllipse* ellipse = dynamic_cast(node->GetData()); if (m_Controls->m_ConstantRadiusBox->isChecked()) { ellipse->SetTreatAsCircle(true); mitk::Point2D c = ellipse->GetControlPoint(0); mitk::Point2D p = ellipse->GetControlPoint(1); mitk::Vector2D v = p-c; if (count==0) { radius = v.GetVnlVector().magnitude(); ellipse->SetControlPoint(1, p); } else { v.Normalize(); v *= radius; ellipse->SetControlPoint(1, c+v); } } fib.push_back(ellipse); std::map::iterator it = m_DataNodeToPlanarFigureData.find(node.GetPointer()); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; flip.push_back(data.m_Flipped); } else flip.push_back(0); } count++; } if (fib.size()>1) { fiducials.push_back(fib); fliplist.push_back(flip); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); if (fib.size()<3) return; } itk::FibersFromPlanarFiguresFilter::Pointer filter = itk::FibersFromPlanarFiguresFilter::New(); filter->SetFiducials(fiducials); filter->SetFlipList(fliplist); switch(m_Controls->m_DistributionBox->currentIndex()){ case 0: filter->SetFiberDistribution(itk::FibersFromPlanarFiguresFilter::DISTRIBUTE_UNIFORM); break; case 1: filter->SetFiberDistribution(itk::FibersFromPlanarFiguresFilter::DISTRIBUTE_GAUSSIAN); filter->SetVariance(m_Controls->m_VarianceBox->value()); break; } filter->SetDensity(m_Controls->m_FiberDensityBox->value()); filter->SetTension(m_Controls->m_TensionBox->value()); filter->SetContinuity(m_Controls->m_ContinuityBox->value()); filter->SetBias(m_Controls->m_BiasBox->value()); filter->SetFiberSampling(m_Controls->m_FiberSamplingBox->value()); filter->Update(); vector< mitk::FiberBundleX::Pointer > fiberBundles = filter->GetFiberBundles(); for (int i=0; iSetData( fiberBundles.at(i) ); if (fiberBundles.at(i)->GetNumFibers()>50000) m_SelectedBundles.at(i)->SetVisibility(false); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::GenerateImage() { itk::ImageRegion<3> imageRegion; imageRegion.SetSize(0, m_Controls->m_SizeX->value()); imageRegion.SetSize(1, m_Controls->m_SizeY->value()); imageRegion.SetSize(2, m_Controls->m_SizeZ->value()); mitk::Vector3D spacing; spacing[0] = m_Controls->m_SpacingX->value(); spacing[1] = m_Controls->m_SpacingY->value(); spacing[2] = m_Controls->m_SpacingZ->value(); mitk::Point3D origin; origin[0] = spacing[0]/2; origin[1] = spacing[1]/2; origin[2] = spacing[2]/2; itk::Matrix directionMatrix; directionMatrix.SetIdentity(); if (m_SelectedBundle.IsNull()) { mitk::Image::Pointer image = mitk::ImageGenerator::GenerateGradientImage( m_Controls->m_SizeX->value(), m_Controls->m_SizeY->value(), m_Controls->m_SizeZ->value(), m_Controls->m_SpacingX->value(), m_Controls->m_SpacingY->value(), m_Controls->m_SpacingZ->value()); mitk::Geometry3D* geom = image->GetGeometry(); geom->SetOrigin(origin); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); node->SetName("Dummy"); GetDataStorage()->Add(node); m_SelectedImage = node; mitk::BaseData::Pointer basedata = node->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } UpdateGui(); return; } DiffusionSignalModel::GradientListType gradientList; double bVal = 1000; if (m_SelectedDWI.IsNull()) { gradientList = GenerateHalfShell(m_Controls->m_NumGradientsBox->value());; bVal = m_Controls->m_BvalueBox->value(); } else { mitk::DiffusionImage::Pointer dwi = dynamic_cast*>(m_SelectedDWI->GetData()); imageRegion = dwi->GetVectorImage()->GetLargestPossibleRegion(); spacing = dwi->GetVectorImage()->GetSpacing(); origin = dwi->GetVectorImage()->GetOrigin(); directionMatrix = dwi->GetVectorImage()->GetDirection(); bVal = dwi->GetB_Value(); mitk::DiffusionImage::GradientDirectionContainerType::Pointer dirs = dwi->GetDirections(); for (int i=0; iSize(); i++) { DiffusionSignalModel::GradientType g; g[0] = dirs->at(i)[0]; g[1] = dirs->at(i)[1]; g[2] = dirs->at(i)[2]; gradientList.push_back(g); } } - // storage for generated phantom image - mitk::DataNode::Pointer resultNode = mitk::DataNode::New(); - - // signal models - QString signalModelString("Ball"); - itk::TractsToDWIImageFilter::DiffusionModelList fiberModelList, nonFiberModelList; - mitk::TensorModel tensorModel; - mitk::StickModel stickModel; - - // free diffusion - mitk::BallModel ballModel; - ballModel.SetGradientList(gradientList); - ballModel.SetBvalue(bVal); - ballModel.SetDiffusivity(m_Controls->m_BallD->value()); - ballModel.SetSignalScale(m_Controls->m_NonFiberS0Box->value()); - ballModel.SetRelaxationT2(m_Controls->m_NonFiberRelaxationT2Box->value()); - nonFiberModelList.push_back(&ballModel); - - resultNode->AddProperty("Fiberfox.Ball.Diffusivity", DoubleProperty::New(m_Controls->m_BallD->value())); - resultNode->AddProperty("Fiberfox.Ball.Scaling", DoubleProperty::New(m_Controls->m_NonFiberS0Box->value())); - if (m_Controls->m_AddT2Smearing->isChecked()) - resultNode->AddProperty("Fiberfox.Ball.T2", DoubleProperty::New(m_Controls->m_NonFiberRelaxationT2Box->value())); - - // intra-axonal diffusion - switch (m_Controls->m_FiberCompartmentModelBox->currentIndex()) - { - case 0: - MITK_INFO << "Using zeppelin model"; - tensorModel.SetGradientList(gradientList); - tensorModel.SetBvalue(bVal); - tensorModel.SetKernelFA(m_Controls->m_TensorFaBox->value()); - tensorModel.SetSignalScale(m_Controls->m_FiberS0Box->value()); - tensorModel.SetRelaxationT2(m_Controls->m_FiberRelaxationT2Box->value()); - fiberModelList.push_back(&tensorModel); - signalModelString += "-Zeppelin"; - resultNode->AddProperty("Fiberfox.Zeppelin.FA", DoubleProperty::New(m_Controls->m_TensorFaBox->value())); - resultNode->AddProperty("Fiberfox.Zeppelin.Scaling", DoubleProperty::New(m_Controls->m_FiberS0Box->value())); - if (m_Controls->m_AddT2Smearing->isChecked()) - resultNode->AddProperty("Fiberfox.Zeppelin.T2", DoubleProperty::New(m_Controls->m_FiberRelaxationT2Box->value())); - break; - case 1: - MITK_INFO << "Using stick model"; - stickModel.SetGradientList(gradientList); - stickModel.SetDiffusivity(m_Controls->m_StickDiffusivityBox->value()); - stickModel.SetSignalScale(m_Controls->m_FiberS0Box->value()); - stickModel.SetRelaxationT2(m_Controls->m_FiberRelaxationT2Box->value()); - fiberModelList.push_back(&stickModel); - signalModelString += "-Stick"; - resultNode->AddProperty("Fiberfox.Stick.Diffusivity", DoubleProperty::New(m_Controls->m_StickDiffusivityBox->value())); - resultNode->AddProperty("Fiberfox.Stick.Scaling", DoubleProperty::New(m_Controls->m_FiberS0Box->value())); - if (m_Controls->m_AddT2Smearing->isChecked()) - resultNode->AddProperty("Fiberfox.Stick.T2", DoubleProperty::New(m_Controls->m_FiberRelaxationT2Box->value())); - break; - } - itk::TractsToDWIImageFilter::KspaceArtifactList artifactList; - // noise model - double snr = m_Controls->m_NoiseLevel->value(); - double noiseVariance = 0; - if (snr <= 0) - snr = 0.0001; - if (snr<=99) + for (int i=0; im_FiberS0Box->value()/snr; - noiseVariance *= noiseVariance; - } - mitk::RicianNoiseModel noiseModel; - noiseModel.SetNoiseVariance(noiseVariance); + // storage for generated phantom image + mitk::DataNode::Pointer resultNode = mitk::DataNode::New(); + + // signal models + QString signalModelString("Ball"); + itk::TractsToDWIImageFilter::DiffusionModelList fiberModelList, nonFiberModelList; + mitk::TensorModel tensorModel; + mitk::StickModel stickModel; + + // free diffusion + mitk::BallModel ballModel; + ballModel.SetGradientList(gradientList); + ballModel.SetBvalue(bVal); + ballModel.SetDiffusivity(m_Controls->m_BallD->value()); + ballModel.SetT2(m_Controls->m_NonFiberT2Box->value()); + nonFiberModelList.push_back(&ballModel); + + resultNode->AddProperty("Fiberfox.Ball.Diffusivity", DoubleProperty::New(m_Controls->m_BallD->value())); + resultNode->AddProperty("Fiberfox.Ball.T2", DoubleProperty::New(m_Controls->m_NonFiberT2Box->value())); + + // intra-axonal diffusion + switch (m_Controls->m_FiberCompartmentModelBox->currentIndex()) + { + case 0: + MITK_INFO << "Using zeppelin model"; + tensorModel.SetGradientList(gradientList); + tensorModel.SetBvalue(bVal); + tensorModel.SetKernelFA(m_Controls->m_TensorFaBox->value()); + tensorModel.SetT2(m_Controls->m_FiberT2Box->value()); + fiberModelList.push_back(&tensorModel); + signalModelString += "-Zeppelin"; + resultNode->AddProperty("Fiberfox.Zeppelin.FA", DoubleProperty::New(m_Controls->m_TensorFaBox->value())); + resultNode->AddProperty("Fiberfox.Zeppelin.T2", DoubleProperty::New(m_Controls->m_FiberT2Box->value())); + break; + case 1: + MITK_INFO << "Using stick model"; + stickModel.SetGradientList(gradientList); + stickModel.SetDiffusivity(m_Controls->m_StickDiffusivityBox->value()); + stickModel.SetT2(m_Controls->m_FiberT2Box->value()); + fiberModelList.push_back(&stickModel); + signalModelString += "-Stick"; + resultNode->AddProperty("Fiberfox.Stick.Diffusivity", DoubleProperty::New(m_Controls->m_StickDiffusivityBox->value())); + resultNode->AddProperty("Fiberfox.Stick.T2", DoubleProperty::New(m_Controls->m_FiberT2Box->value())); + break; + } - // artifact models - QString artifactModelString(""); - mitk::GibbsRingingArtifact gibbsModel; - if (m_Controls->m_AddGibbsRinging->isChecked()) - { - artifactModelString += "_Gibbs-ringing"; - resultNode->AddProperty("Fiberfox.k-Space-Undersampling", IntProperty::New(m_Controls->m_KspaceUndersamplingBox->currentText().toInt())); - gibbsModel.SetKspaceCropping((double)m_Controls->m_KspaceUndersamplingBox->currentText().toInt()); - artifactList.push_back(&gibbsModel); - } + itk::TractsToDWIImageFilter::KspaceArtifactList artifactList; - mitk::T2SmearingArtifact t2Model; - if (m_Controls->m_AddT2Smearing->isChecked()) - { - artifactModelString += "_T2-blurring"; - t2Model.SetReadoutPulseLength(1); - artifactList.push_back(&t2Model); - } + // noise model + double noiseVariance = m_Controls->m_NoiseLevel->value(); + mitk::RicianNoiseModel noiseModel; + noiseModel.SetNoiseVariance(noiseVariance); + + // artifact models + QString artifactModelString(""); + mitk::GibbsRingingArtifact gibbsModel; + if (m_Controls->m_AddGibbsRinging->isChecked()) + { + artifactModelString += "_Gibbs-ringing"; + resultNode->AddProperty("Fiberfox.k-Space-Undersampling", IntProperty::New(m_Controls->m_KspaceUndersamplingBox->currentText().toInt())); + gibbsModel.SetKspaceCropping((double)m_Controls->m_KspaceUndersamplingBox->currentText().toInt()); + artifactList.push_back(&gibbsModel); + } + + mitk::T2SmearingArtifact contrastModel; + contrastModel.SetT2star(this->m_Controls->m_T2starBox->value()); + contrastModel.SetTE(this->m_Controls->m_TEbox->value()); + contrastModel.SetTline(m_Controls->m_LineReadoutTimeBox->value()); + artifactList.push_back(&contrastModel); - for (int i=0; i(m_SelectedBundles.at(i)->GetData()); if (fiberBundle->GetNumFibers()<=0) continue; itk::TractsToDWIImageFilter::Pointer filter = itk::TractsToDWIImageFilter::New(); filter->SetImageRegion(imageRegion); filter->SetSpacing(spacing); filter->SetOrigin(origin); filter->SetDirectionMatrix(directionMatrix); filter->SetFiberBundle(fiberBundle); filter->SetFiberModels(fiberModelList); filter->SetNonFiberModels(nonFiberModelList); filter->SetNoiseModel(&noiseModel); filter->SetKspaceArtifacts(artifactList); filter->SetNumberOfRepetitions(m_Controls->m_RepetitionsBox->value()); filter->SetEnforcePureFiberVoxels(m_Controls->m_EnforcePureFiberVoxelsBox->isChecked()); filter->SetInterpolationShrink(m_Controls->m_InterpolationShrink->value()); + filter->SetFiberRadius(m_Controls->m_FiberRadius->value()); + filter->SetSignalScale(m_Controls->m_SignalScaleBox->value()); if (m_TissueMask.IsNotNull()) { ItkUcharImgType::Pointer mask = ItkUcharImgType::New(); mitk::CastToItkImage(m_TissueMask, mask); filter->SetTissueMask(mask); } filter->Update(); mitk::DiffusionImage::Pointer image = mitk::DiffusionImage::New(); image->SetVectorImage( filter->GetOutput() ); image->SetB_Value(bVal); image->SetDirections(gradientList); image->InitializeFromVectorImage(); resultNode->SetData( image ); - resultNode->SetName(m_SelectedBundle->GetName() + resultNode->SetName(m_SelectedBundles.at(i)->GetName() +"_D"+QString::number(imageRegion.GetSize(0)).toStdString() +"-"+QString::number(imageRegion.GetSize(1)).toStdString() +"-"+QString::number(imageRegion.GetSize(2)).toStdString() +"_S"+QString::number(spacing[0]).toStdString() +"-"+QString::number(spacing[1]).toStdString() +"-"+QString::number(spacing[2]).toStdString() +"_b"+QString::number(bVal).toStdString() - +"_SNR"+QString::number(snr).toStdString() + +"_NOISE"+QString::number(noiseVariance).toStdString() +"_"+signalModelString.toStdString() +artifactModelString.toStdString()); - GetDataStorage()->Add(resultNode, m_SelectedBundle); + GetDataStorage()->Add(resultNode, m_SelectedBundles.at(i)); - resultNode->AddProperty("Fiberfox.SNR", DoubleProperty::New(snr)); + resultNode->AddProperty("Fiberfox.Noise-Variance", DoubleProperty::New(noiseVariance)); resultNode->AddProperty("Fiberfox.Repetitions", IntProperty::New(m_Controls->m_RepetitionsBox->value())); resultNode->AddProperty("Fiberfox.b-value", DoubleProperty::New(bVal)); resultNode->AddProperty("Fiberfox.Model", StringProperty::New(signalModelString.toStdString())); if (m_Controls->m_KspaceImageBox->isChecked()) { itk::Image::Pointer kspace = filter->GetKspaceImage(); mitk::Image::Pointer image = mitk::Image::New(); image->InitializeByItk(kspace.GetPointer()); image->SetVolume(kspace->GetBufferPointer()); mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData( image ); - node->SetName(m_SelectedBundle->GetName()+"_k-space"); - GetDataStorage()->Add(node, m_SelectedBundle); + node->SetName(m_SelectedBundles.at(i)->GetName()+"_k-space"); + GetDataStorage()->Add(node, m_SelectedBundles.at(i)); } mitk::BaseData::Pointer basedata = resultNode->GetData(); if (basedata.IsNotNull()) { mitk::RenderingManager::GetInstance()->InitializeViews( basedata->GetTimeSlicedGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } } void QmitkFiberfoxView::ApplyTransform() { vector< mitk::DataNode::Pointer > selectedBundles; for( int i=0; iGetDerivations(m_SelectedImages.at(i)); for( mitk::DataStorage::SetOfObjects::const_iterator it = derivations->begin(); it != derivations->end(); ++it ) { mitk::DataNode::Pointer fibNode = *it; if ( fibNode.IsNotNull() && dynamic_cast(fibNode->GetData()) ) selectedBundles.push_back(fibNode); } } if (selectedBundles.empty()) selectedBundles = m_SelectedBundles2; if (!selectedBundles.empty()) { std::vector::const_iterator it = selectedBundles.begin(); for (it; it!=selectedBundles.end(); ++it) { mitk::FiberBundleX::Pointer fib = dynamic_cast((*it)->GetData()); fib->RotateAroundAxis(m_Controls->m_XrotBox->value(), m_Controls->m_YrotBox->value(), m_Controls->m_ZrotBox->value()); fib->TranslateFibers(m_Controls->m_XtransBox->value(), m_Controls->m_YtransBox->value(), m_Controls->m_ZtransBox->value()); fib->ScaleFibers(m_Controls->m_XscaleBox->value(), m_Controls->m_YscaleBox->value(), m_Controls->m_ZscaleBox->value()); // handle child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse* pe = dynamic_cast(fiducialNode->GetData()); mitk::Geometry3D* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< float, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< float, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< float, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< float, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); // implicit translation mitk::Vector3D trans; trans[0] = geom->GetOrigin()[0]-fib->GetGeometry()->GetCenter()[0]; trans[1] = geom->GetOrigin()[1]-fib->GetGeometry()->GetCenter()[1]; trans[2] = geom->GetOrigin()[2]-fib->GetGeometry()->GetCenter()[2]; mitk::Vector3D newWc = rot*trans; newWc = newWc-trans; geom->Translate(newWc); } } } } } else { for (int i=0; i(m_SelectedFiducials.at(i)->GetData()); mitk::Geometry3D* geom = pe->GetGeometry(); // translate mitk::Vector3D world; world[0] = m_Controls->m_XtransBox->value(); world[1] = m_Controls->m_YtransBox->value(); world[2] = m_Controls->m_ZtransBox->value(); geom->Translate(world); // calculate rotation matrix double x = m_Controls->m_XrotBox->value()*M_PI/180; double y = m_Controls->m_YrotBox->value()*M_PI/180; double z = m_Controls->m_ZrotBox->value()*M_PI/180; itk::Matrix< float, 3, 3 > rotX; rotX.SetIdentity(); rotX[1][1] = cos(x); rotX[2][2] = rotX[1][1]; rotX[1][2] = -sin(x); rotX[2][1] = -rotX[1][2]; itk::Matrix< float, 3, 3 > rotY; rotY.SetIdentity(); rotY[0][0] = cos(y); rotY[2][2] = rotY[0][0]; rotY[0][2] = sin(y); rotY[2][0] = -rotY[0][2]; itk::Matrix< float, 3, 3 > rotZ; rotZ.SetIdentity(); rotZ[0][0] = cos(z); rotZ[1][1] = rotZ[0][0]; rotZ[0][1] = -sin(z); rotZ[1][0] = -rotZ[0][1]; itk::Matrix< float, 3, 3 > rot = rotZ*rotY*rotX; // transform control point coordinate into geometry translation geom->SetOrigin(pe->GetWorldControlPoint(0)); mitk::Point2D cp; cp.Fill(0.0); pe->SetControlPoint(0, cp); // rotate fiducial geom->GetIndexToWorldTransform()->SetMatrix(rot*geom->GetIndexToWorldTransform()->GetMatrix()); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::CopyBundles() { if ( m_SelectedBundles.size()<1 ){ QMessageBox::information( NULL, "Warning", "Select at least one fiber bundle!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least one fiber bundle!"; return; } std::vector::const_iterator it = m_SelectedBundles.begin(); for (it; it!=m_SelectedBundles.end(); ++it) { // find parent image mitk::DataNode::Pointer parentNode; mitk::DataStorage::SetOfObjects::ConstPointer parentImgs = GetDataStorage()->GetSources(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = parentImgs->begin(); it2 != parentImgs->end(); ++it2 ) { mitk::DataNode::Pointer pImgNode = *it2; if ( pImgNode.IsNotNull() && dynamic_cast(pImgNode->GetData()) ) { parentNode = pImgNode; break; } } mitk::FiberBundleX::Pointer fib = dynamic_cast((*it)->GetData()); mitk::FiberBundleX::Pointer newBundle = fib->GetDeepCopy(); QString name((*it)->GetName().c_str()); name += "_copy"; mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); if (parentNode.IsNotNull()) GetDataStorage()->Add(fbNode, parentNode); else GetDataStorage()->Add(fbNode); // copy child fiducials if (m_Controls->m_IncludeFiducials->isChecked()) { mitk::DataStorage::SetOfObjects::ConstPointer derivations = GetDataStorage()->GetDerivations(*it); for( mitk::DataStorage::SetOfObjects::const_iterator it2 = derivations->begin(); it2 != derivations->end(); ++it2 ) { mitk::DataNode::Pointer fiducialNode = *it2; if ( fiducialNode.IsNotNull() && dynamic_cast(fiducialNode->GetData()) ) { mitk::PlanarEllipse::Pointer pe = mitk::PlanarEllipse::New(); pe->DeepCopy(dynamic_cast(fiducialNode->GetData())); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); newNode->SetData(pe); newNode->SetName(fiducialNode->GetName()); GetDataStorage()->Add(newNode, fbNode); } } } } mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::JoinBundles() { if ( m_SelectedBundles.size()<2 ){ QMessageBox::information( NULL, "Warning", "Select at least two fiber bundles!"); MITK_WARN("QmitkFiberProcessingView") << "Select at least two fiber bundles!"; return; } std::vector::const_iterator it = m_SelectedBundles.begin(); mitk::FiberBundleX::Pointer newBundle = dynamic_cast((*it)->GetData()); QString name(""); name += QString((*it)->GetName().c_str()); ++it; for (it; it!=m_SelectedBundles.end(); ++it) { newBundle = newBundle->AddBundle(dynamic_cast((*it)->GetData())); name += "+"+QString((*it)->GetName().c_str()); } mitk::DataNode::Pointer fbNode = mitk::DataNode::New(); fbNode->SetData(newBundle); fbNode->SetName(name.toStdString()); fbNode->SetVisibility(true); GetDataStorage()->Add(fbNode); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkFiberfoxView::UpdateGui() { m_Controls->m_FiberBundleLabel->setText("mandatory"); m_Controls->m_GeometryFrame->setEnabled(true); m_Controls->m_GeometryMessage->setVisible(false); m_Controls->m_DiffusionPropsMessage->setVisible(false); m_Controls->m_FiberGenMessage->setVisible(true); m_Controls->m_TransformBundlesButton->setEnabled(false); m_Controls->m_CopyBundlesButton->setEnabled(false); m_Controls->m_GenerateFibersButton->setEnabled(false); m_Controls->m_FlipButton->setEnabled(false); m_Controls->m_CircleButton->setEnabled(false); m_Controls->m_BvalueBox->setEnabled(true); m_Controls->m_NumGradientsBox->setEnabled(true); m_Controls->m_JoinBundlesButton->setEnabled(false); m_Controls->m_AlignOnGrid->setEnabled(false); if (m_SelectedFiducial.IsNotNull()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_FlipButton->setEnabled(true); m_Controls->m_AlignOnGrid->setEnabled(true); } if (m_SelectedImage.IsNotNull() || m_SelectedBundle.IsNotNull()) { m_Controls->m_TransformBundlesButton->setEnabled(true); m_Controls->m_CircleButton->setEnabled(true); m_Controls->m_FiberGenMessage->setVisible(false); m_Controls->m_AlignOnGrid->setEnabled(true); } if (m_TissueMask.IsNotNull()) { m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } if (m_SelectedDWI.IsNotNull()) { m_Controls->m_DiffusionPropsMessage->setVisible(true); m_Controls->m_BvalueBox->setEnabled(false); m_Controls->m_NumGradientsBox->setEnabled(false); m_Controls->m_GeometryMessage->setVisible(true); m_Controls->m_GeometryFrame->setEnabled(false); } if (m_SelectedBundle.IsNotNull()) { m_Controls->m_CopyBundlesButton->setEnabled(true); m_Controls->m_GenerateFibersButton->setEnabled(true); m_Controls->m_FiberBundleLabel->setText(m_SelectedBundle->GetName().c_str()); if (m_SelectedBundles.size()>1) m_Controls->m_JoinBundlesButton->setEnabled(true); } } void QmitkFiberfoxView::OnSelectionChanged( berry::IWorkbenchPart::Pointer, const QList& nodes ) { m_SelectedBundles2.clear(); m_SelectedImages.clear(); m_SelectedFiducials.clear(); m_SelectedFiducial = NULL; m_TissueMask = NULL; m_SelectedBundles.clear(); m_SelectedBundle = NULL; m_SelectedImage = NULL; m_SelectedDWI = NULL; m_Controls->m_TissueMaskLabel->setText("optional"); // iterate all selected objects, adjust warning visibility for( int i=0; i*>(node->GetData()) ) { m_SelectedDWI = node; m_SelectedImage = node; m_SelectedImages.push_back(node); } else if( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedImages.push_back(node); m_SelectedImage = node; bool isBinary = false; node->GetPropertyValue("binary", isBinary); if (isBinary) { m_TissueMask = dynamic_cast(node->GetData()); m_Controls->m_TissueMaskLabel->setText(node->GetName().c_str()); } } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedBundles2.push_back(node); if (m_Controls->m_RealTimeFibers->isChecked() && node!=m_SelectedBundle) { m_SelectedBundle = node; m_SelectedBundles.push_back(node); mitk::FiberBundleX::Pointer newFib = dynamic_cast(node->GetData()); if (newFib->GetNumFibers()!=m_Controls->m_FiberDensityBox->value()) GenerateFibers(); } else { m_SelectedBundle = node; m_SelectedBundles.push_back(node); } } else if ( node.IsNotNull() && dynamic_cast(node->GetData()) ) { m_SelectedFiducials.push_back(node); m_SelectedFiducial = node; m_SelectedBundles.clear(); mitk::DataStorage::SetOfObjects::ConstPointer parents = GetDataStorage()->GetSources(node); for( mitk::DataStorage::SetOfObjects::const_iterator it = parents->begin(); it != parents->end(); ++it ) { mitk::DataNode::Pointer pNode = *it; if ( pNode.IsNotNull() && dynamic_cast(pNode->GetData()) ) { m_SelectedBundle = pNode; m_SelectedBundles.push_back(pNode); } } } } UpdateGui(); } void QmitkFiberfoxView::EnableCrosshairNavigation() { MITK_DEBUG << "EnableCrosshairNavigation"; // enable the crosshair navigation if (mitk::ILinkedRenderWindowPart* linkedRenderWindow = dynamic_cast(this->GetRenderWindowPart())) { MITK_DEBUG << "enabling linked navigation"; linkedRenderWindow->EnableLinkedNavigation(true); // linkedRenderWindow->EnableSlicingPlanes(true); } if (m_Controls->m_RealTimeFibers->isChecked()) GenerateFibers(); } void QmitkFiberfoxView::DisableCrosshairNavigation() { MITK_DEBUG << "DisableCrosshairNavigation"; // disable the crosshair navigation during the drawing if (mitk::ILinkedRenderWindowPart* linkedRenderWindow = dynamic_cast(this->GetRenderWindowPart())) { MITK_DEBUG << "disabling linked navigation"; linkedRenderWindow->EnableLinkedNavigation(false); // linkedRenderWindow->EnableSlicingPlanes(false); } } void QmitkFiberfoxView::NodeRemoved(const mitk::DataNode* node) { if (node == m_SelectedImage) m_SelectedImage = NULL; if (node == m_SelectedBundle) m_SelectedBundle = NULL; mitk::DataNode* nonConstNode = const_cast(node); std::map::iterator it = m_DataNodeToPlanarFigureData.find(nonConstNode); if( it != m_DataNodeToPlanarFigureData.end() ) { QmitkPlanarFigureData& data = it->second; // remove observers data.m_Figure->RemoveObserver( data.m_EndPlacementObserverTag ); data.m_Figure->RemoveObserver( data.m_SelectObserverTag ); data.m_Figure->RemoveObserver( data.m_StartInteractionObserverTag ); data.m_Figure->RemoveObserver( data.m_EndInteractionObserverTag ); m_DataNodeToPlanarFigureData.erase( it ); } } void QmitkFiberfoxView::NodeAdded( const mitk::DataNode* node ) { // add observer for selection in renderwindow mitk::PlanarFigure* figure = dynamic_cast(node->GetData()); bool isPositionMarker (false); node->GetBoolProperty("isContourMarker", isPositionMarker); if( figure && !isPositionMarker ) { MITK_DEBUG << "figure added. will add interactor if needed."; mitk::PlanarFigureInteractor::Pointer figureInteractor = dynamic_cast(node->GetInteractor()); mitk::DataNode* nonConstNode = const_cast( node ); if(figureInteractor.IsNull()) { figureInteractor = mitk::PlanarFigureInteractor::New("PlanarFigureInteractor", nonConstNode); } else { // just to be sure that the interactor is not added twice mitk::GlobalInteraction::GetInstance()->RemoveInteractor(figureInteractor); } MITK_DEBUG << "adding interactor to globalinteraction"; mitk::GlobalInteraction::GetInstance()->AddInteractor(figureInteractor); MITK_DEBUG << "will now add observers for planarfigure"; QmitkPlanarFigureData data; data.m_Figure = figure; // // add observer for event when figure has been placed typedef itk::SimpleMemberCommand< QmitkFiberfoxView > SimpleCommandType; // SimpleCommandType::Pointer initializationCommand = SimpleCommandType::New(); // initializationCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureInitialized ); // data.m_EndPlacementObserverTag = figure->AddObserver( mitk::EndPlacementPlanarFigureEvent(), initializationCommand ); // add observer for event when figure is picked (selected) typedef itk::MemberCommand< QmitkFiberfoxView > MemberCommandType; MemberCommandType::Pointer selectCommand = MemberCommandType::New(); selectCommand->SetCallbackFunction( this, &QmitkFiberfoxView::PlanarFigureSelected ); data.m_SelectObserverTag = figure->AddObserver( mitk::SelectPlanarFigureEvent(), selectCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer startInteractionCommand = SimpleCommandType::New(); startInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::DisableCrosshairNavigation); data.m_StartInteractionObserverTag = figure->AddObserver( mitk::StartInteractionPlanarFigureEvent(), startInteractionCommand ); // add observer for event when interaction with figure starts SimpleCommandType::Pointer endInteractionCommand = SimpleCommandType::New(); endInteractionCommand->SetCallbackFunction( this, &QmitkFiberfoxView::EnableCrosshairNavigation); data.m_EndInteractionObserverTag = figure->AddObserver( mitk::EndInteractionPlanarFigureEvent(), endInteractionCommand ); m_DataNodeToPlanarFigureData[nonConstNode] = data; } } void QmitkFiberfoxView::PlanarFigureSelected( itk::Object* object, const itk::EventObject& ) { mitk::TNodePredicateDataType::Pointer isPf = mitk::TNodePredicateDataType::New(); mitk::DataStorage::SetOfObjects::ConstPointer allPfs = this->GetDataStorage()->GetSubset( isPf ); for ( mitk::DataStorage::SetOfObjects::const_iterator it = allPfs->begin(); it!=allPfs->end(); ++it) { mitk::DataNode* node = *it; if( node->GetData() == object ) { node->SetSelected(true); m_SelectedFiducial = node; } else node->SetSelected(false); } UpdateGui(); this->RequestRenderWindowUpdate(); } void QmitkFiberfoxView::SetFocus() { m_Controls->m_CircleButton->setFocus(); } diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h index 757addc9d2..63ff823723 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxView.h @@ -1,137 +1,136 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include "ui_QmitkFiberfoxViewControls.h" #include #include #include #include #include /*! \brief View for fiber based diffusion software phantoms (Fiberfox). \sa QmitkFunctionality \ingroup Functionalities */ // Forward Qt class declarations using namespace std; class QmitkFiberfoxView : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const string VIEW_ID; QmitkFiberfoxView(); virtual ~QmitkFiberfoxView(); virtual void CreateQtPartControl(QWidget *parent); void SetFocus(); typedef itk::Image ItkUcharImgType; typedef itk::Vector GradientType; typedef vector GradientListType; template vector > MakeGradientList() ; protected slots: void OnDrawROI(); ///< adds new ROI, handles interactors etc. void OnAddBundle(); ///< adds new fiber bundle to datastorage void OnFlipButton(); ///< negate one coordinate of the fiber waypoints in the selcted planar figure. needed in case of unresolvable twists void GenerateFibers(); ///< generate fibers from the selected ROIs void GenerateImage(); ///< generate artificial image from the selected fiber bundle void JoinBundles(); ///< merges selcted fiber bundles into one void CopyBundles(); ///< add copy of the selected bundle to the datamanager void ApplyTransform(); ///< rotate and shift selected bundles void AlignOnGrid(); ///< shift selected fiducials to nearest voxel center void FiberModelFrameVisibility(int index);///< only show parameters of selected fiber model type void NonFiberModelFrameVisibility(int index);///< only show parameters of selected non-fiber model type - void ShowAdvancedFiberOptions(int state); + void ShowAdvancedOptions(int state); /** update fibers if any parameter changes */ void OnFiberDensityChanged(int value); void OnFiberSamplingChanged(int value); void OnTensionChanged(double value); void OnContinuityChanged(double value); void OnBiasChanged(double value); void OnVarianceChanged(double value); void OnDistributionChanged(int value); - void OnAddT2Smearing(int value); void OnAddGibbsRinging(int value); void OnConstantRadius(int value); protected: /// \brief called by QmitkFunctionality when DataManager's selection has changed virtual void OnSelectionChanged(berry::IWorkbenchPart::Pointer, const QList&); GradientListType GenerateHalfShell(int NPoints); ///< generate vectors distributed over the halfsphere Ui::QmitkFiberfoxViewControls* m_Controls; void UpdateGui(); ///< enable/disbale buttons etc. according to current datamanager selection void PlanarFigureSelected( itk::Object* object, const itk::EventObject& ); void EnableCrosshairNavigation(); ///< enable crosshair navigation if planar figure interaction ends void DisableCrosshairNavigation(); ///< disable crosshair navigation if planar figure interaction starts void NodeAdded( const mitk::DataNode* node ); ///< add observers void NodeRemoved(const mitk::DataNode* node); ///< remove observers /** structure to keep track of planar figures and observers */ struct QmitkPlanarFigureData { QmitkPlanarFigureData() : m_Figure(0) , m_EndPlacementObserverTag(0) , m_SelectObserverTag(0) , m_StartInteractionObserverTag(0) , m_EndInteractionObserverTag(0) , m_Flipped(0) { } mitk::PlanarFigure* m_Figure; unsigned int m_EndPlacementObserverTag; unsigned int m_SelectObserverTag; unsigned int m_StartInteractionObserverTag; unsigned int m_EndInteractionObserverTag; unsigned int m_Flipped; }; std::map m_DataNodeToPlanarFigureData; ///< map each planar figure uniquely to a QmitkPlanarFigureData mitk::Image::Pointer m_TissueMask; ///< mask defining which regions of the image should contain signal and which are containing only noise mitk::DataNode::Pointer m_SelectedFiducial; ///< selected planar ellipse mitk::DataNode::Pointer m_SelectedImage; mitk::DataNode::Pointer m_SelectedBundle; mitk::DataNode::Pointer m_SelectedDWI; vector< mitk::DataNode::Pointer > m_SelectedBundles; vector< mitk::DataNode::Pointer > m_SelectedBundles2; vector< mitk::DataNode::Pointer > m_SelectedFiducials; vector< mitk::DataNode::Pointer > m_SelectedImages; }; diff --git a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui index b8a746e398..a172316b28 100644 --- a/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.diffusionimaging/src/internal/QmitkFiberfoxViewControls.ui @@ -1,1950 +1,2064 @@ QmitkFiberfoxViewControls 0 0 493 - 1140 + 1206 Form 0 Fiber Definition Qt::Vertical 20 40 color: rgb(255, 0, 0); Please select an image or an existing fiber bundle to draw the fiber fiducials. If you can't provide a suitable image, generate one using the "Signal Generation" tab. Qt::AutoText Qt::AlignJustify|Qt::AlignVCenter true Fiducial Options All fiducials are treated as circles with the same radius as the first fiducial. Use Constant Fiducial Radius false false Align selected fiducials with voxel grid. Shifts selected fiducials to nearest voxel center. Align With Grid Operations false Copy Bundles false Transform Selection QFrame::NoFrame QFrame::Raised 0 Y false Rotation angle (in degree) around x-axis. -360.000000000000000 360.000000000000000 0.100000000000000 Axis: false Rotation angle (in degree) around y-axis. -360.000000000000000 360.000000000000000 0.100000000000000 Translation: false Translation (in mm) in direction of the z-axis. - -100.000000000000000 + -1000.000000000000000 - 100.000000000000000 + 1000.000000000000000 0.100000000000000 Translation (in mm) in direction of the y-axis. - -100.000000000000000 + -1000.000000000000000 - 100.000000000000000 + 1000.000000000000000 0.100000000000000 X false Rotation: false Z false Rotation angle (in degree) around z-axis. -360.000000000000000 360.000000000000000 0.100000000000000 Translation (in mm) in direction of the x-axis. - -100.000000000000000 + -1000.000000000000000 - 100.000000000000000 + 1000.000000000000000 0.100000000000000 Scaling: false Scaling factor for selected fiber bundle along the x-axis. 0.010000000000000 - 1.000000000000000 + 10.000000000000000 0.010000000000000 1.000000000000000 Scaling factor for selected fiber bundle along the y-axis. 0.010000000000000 - 1.000000000000000 + 10.000000000000000 0.010000000000000 1.000000000000000 Scaling factor for selected fiber bundle along the z-axis. 0.010000000000000 - 1.000000000000000 + 10.000000000000000 0.010000000000000 1.000000000000000 false Join Bundles If checked, the fiducials belonging to the modified bundle are also modified. Include Fiducials true Fiber Options QFrame::NoFrame QFrame::Raised 0 QFrame::NoFrame QFrame::Raised 0 Tension: false Fiber Sampling: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Fiber sampling points (per cm) 1 100 1 10 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 Bias: false Continuity: false 3 -1.000000000000000 1.000000000000000 0.100000000000000 0.000000000000000 QFrame::NoFrame QFrame::Raised - - - QFormLayout::AllNonFixedFieldsGrow + + + 0 6 - - 0 - - + #Fibers: false - + Specify number of fibers to generate for the selected bundle. 1 1000000 100 100 false Generate Fibers QFrame::NoFrame QFrame::Raised 0 Select fiber distribution inside of the fiducials. Uniform Gaussian Fiber Distribution: false Variance of the gaussian 3 0.001000000000000 10.000000000000000 0.010000000000000 0.100000000000000 QFrame::NoFrame QFrame::Raised 0 Disable to only generate fibers if "Generate Fibers" button is pressed. Real Time Fibers true - + Disable to only generate fibers if "Generate Fibers" button is pressed. Advanced Options false QFrame::NoFrame QFrame::Raised 0 false 30 30 Draw elliptical fiducial. :/QmitkDiffusionImaging/circle.png:/QmitkDiffusionImaging/circle.png 32 32 false true false 30 30 Flip fiber waypoints of selcted fiducial around one axis. :/QmitkDiffusionImaging/refresh.xpm:/QmitkDiffusionImaging/refresh.xpm 32 32 false true Qt::Horizontal 40 20 Signal Generation Data Fiber Bundle: false <html><head/><body><p><span style=" color:#ff0000;">mandatory</span></p></body></html> true Tissue Mask: false <html><head/><body><p><span style=" color:#969696;">optional</span></p></body></html> true Noise and Artifacts - + true QFrame::NoFrame QFrame::Raised 6 0 k-Space Undersampling: false Image is upsampled using this factor, afterwards fourier transformed, cropped to the original size and then inverse fourier transformed. 1 2 4 8 16 32 64 128 256 - - - Add T2 Blurring + + + true - - false + + QFrame::NoFrame + + QFrame::Raised + + + + QFormLayout::AllNonFixedFieldsGrow + + + 0 + + + 0 + + + 0 + + QFrame::NoFrame QFrame::Raised 0 - SNR: + Variance: - Signal to noise ratio (for values > 99, no noise at all is added to the image). Value relative to the fiber signal scaling factor. + Variance of Rician noise model. 4 0.000000000000000 - 100.000000000000000 + 100000.000000000000000 0.001000000000000 25.000000000000000 - - - true - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - - - - - - - - - - - - Fiber T2: - - - false - - - - - - - T2 of fiber tissue (in milliseconds). - - - 1 - - - 10000 - - - 1 - - - 90 - - - - - - - - - - - - - - - - Non Fiber T2: - - - false - - - - - - - T2 of non-fiber tissue (in milliseconds). - - - 1 - - - 10000 - - - 1 - - - 2200 - - - - - - - Add Gibbs Ringing false true Start DWI generation from selected fiebr bundle. If no fiber bundle is selected, a grayscale image containing a simple gradient is generated. Generate Image Intra-axonal Compartment false false QFrame::NoFrame QFrame::Raised 0 Determins anisotropy of kernel tensor (zeppelin-model). 0.010000000000000 1.000000000000000 0.100000000000000 0.700000000000000 Fractional Anisotropy: Select signal model for intra-axonal compartment. Zeppelin Model Stick Model QFrame::NoFrame QFrame::Raised 0 - + - Signal Scale: + T2 relaxation: false - + - Scaling factor for intra-axonal signal. + T2 of intra axonal compartment (in milliseconds). - 0 + 1 10000 1 - 200 + 90 QFrame::NoFrame QFrame::Raised 0 Diffusivity parameter of the stick-model. 4 0.000100000000000 1.000000000000000 0.000500000000000 0.005000000000000 Diffusivity: Image Settings - - + + QFrame::NoFrame QFrame::Raised - + 0 - - - - 3 + + 6 + + + + + Fiber Radius: - - 0.100000000000000 + + + + + + Output k-Space Image - - 50.000000000000000 + + false - - 0.100000000000000 + + + + + + Treat voxel content as fiber-only if at least one fiber is present. - - 2.500000000000000 + + Enforce Pure Fiber Voxels + + + false - - + + - Image Spacing: + Repetitions: - - - - 3 + + + + Number of signal averages. Increase to reduce noise. - 0.100000000000000 + 1 - 50.000000000000000 + 100 - 0.100000000000000 + 1 - 2.500000000000000 + 1 - - - - 3 - - - 0.100000000000000 - - - 50.000000000000000 + + + + - - 0.100000000000000 + + - - 2.500000000000000 + + - - - - - Image Dimensions: + T2* relaxation: + + + false - - + + - Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. + Scaling factor for signal. - 1 + 0 - 1000 + 10000 1 - 32 + 200 - - + + - Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. + Large values shrink (towards nearest neighbour interpolation), small values strech interpolation function (towards linear interpolation). 1 - 100 - - - 1 + 10000 - 32 + 10 - - + + - Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. + Fiber radius used to calculate volume fractions (in µm). Set to 0 for automatic radius estimation. - 1 + 0 - 100 + 1000 - + + 0 + + + + + + + T2* relaxation time (in milliseconds). + + + 1 + + + 10000 + + 1 - 5 + 50 + + + + + + + Interpolation Shrink: + + + + + + + TE in milliseconds + + + 1 + + + 10000 + + + 1 + + + 100 + + + + + + + + + + + + + + + + Signal Scale: + + + false + + + + + + + + + + + + + + + + Echo time TE: + + + false + + + + + + + + + + + + + + + + Line readout time: + + + false + + + + + + + T2* relaxation time (in milliseconds). + + + 100.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + color: rgb(255, 0, 0); + + + Using mask image geometry! + + + QFrame::NoFrame QFrame::Raised - - - QFormLayout::AllNonFixedFieldsGrow - - - 6 - - - 6 - + 0 - + + 6 + + - #Gradient Directions: + Gradient Directions: - + Number of gradient directions distributed over the half sphere. 0 10000 1 - 60 + 30 - + b-Value: false - + b-value in mm/s² 0 10000 100 1000 - - + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + + + 3 + + + 0.100000000000000 + + + 50.000000000000000 + + + 0.100000000000000 + + + 2.500000000000000 + + + + + - Repetitions: + Image Spacing: - - + + + + 3 + + + 0.100000000000000 + + + 50.000000000000000 + + + 0.100000000000000 + + + 2.500000000000000 + + + + + + + 3 + + + 0.100000000000000 + + + 50.000000000000000 + + + 0.100000000000000 + + + 2.500000000000000 + + + + + + + Image Dimensions: + + + + + - Number of signal averages. Increase to reduce noise. + Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 - 100 + 1000 1 - 1 + 32 - - - - Interpolation Shrink: + + + + Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. + + + 1 + + + 100 + + + 1 + + + 32 - - + + - Large values shrink (towards nearest neighbour interpolation), small values strech interpolation function (towards linear interpolation). + Fiber sampling factor which determines the accuracy of the calculated fiber and non-fiber volume fractions. 1 - 10000 + 100 + + + 1 - 10 + 5 - - - - color: rgb(255, 0, 0); - - - Using mask image geometry! - - - - - - - Treat voxel content as fiber-only if at least one fiber is present. - - - Enforce Pure Fiber Voxels - - - false - - - color: rgb(255, 0, 0); Using gradients of selected DWI! - + - Output k-Space Image - - - false + Advanced Options Qt::Vertical 20 40 Extra-axonal Compartment Select signal model for extra-axonal compartment. Ball Model QFrame::NoFrame QFrame::Raised 0 - - - - Diffusivity: - - - Diffusivity parameter of the ball-model. 4 0.000100000000000 1.000000000000000 0.000500000000000 0.001000000000000 + + + + Diffusivity: + + + - + - Signal Scale: + T2 relaxation: false - + - Scaling factor extra-axonal signal. + T2 of extra axonal compartment (in milliseconds). - 0 + 1 10000 1 100 tabWidget m_CircleButton m_FlipButton m_RealTimeFibers - m_AdvancedFiberOptionsBox + m_AdvancedOptionsBox m_DistributionBox m_VarianceBox m_FiberDensityBox m_FiberSamplingBox m_TensionBox m_ContinuityBox m_BiasBox m_GenerateFibersButton m_ConstantRadiusBox m_AlignOnGrid m_XrotBox m_YrotBox m_ZrotBox m_XtransBox m_YtransBox m_ZtransBox m_XscaleBox m_YscaleBox m_ZscaleBox m_TransformBundlesButton m_CopyBundlesButton m_JoinBundlesButton m_IncludeFiducials m_GenerateImageButton m_SizeX m_SizeY m_SizeZ m_SpacingX m_SpacingY m_SpacingZ m_NumGradientsBox m_BvalueBox m_RepetitionsBox + m_SignalScaleBox + m_TEbox + m_LineReadoutTimeBox + m_T2starBox + m_FiberRadius m_InterpolationShrink m_EnforcePureFiberVoxelsBox m_KspaceImageBox + m_AdvancedOptionsBox_2 m_FiberCompartmentModelBox m_TensorFaBox m_StickDiffusivityBox - m_FiberS0Box + m_FiberT2Box m_NonFiberCompartmentModelBox m_BallD - m_NonFiberS0Box + m_NonFiberT2Box m_NoiseLevel - m_AddT2Smearing - m_FiberRelaxationT2Box - m_NonFiberRelaxationT2Box - m_AddGibbsRinging m_KspaceUndersamplingBox + m_AddGibbsRinging diff --git a/Utilities/tinyxml/tinyxml.h b/Utilities/tinyxml/tinyxml.h index 74b6d0de13..dbc96be031 100644 --- a/Utilities/tinyxml/tinyxml.h +++ b/Utilities/tinyxml/tinyxml.h @@ -1,1804 +1,1820 @@ +/*=================================================================== + + The Medical Imaging Interaction Toolkit (MITK) + + Copyright (c) German Cancer Research Center, + Division of Medical and Biological Informatics. + All rights reserved. + + This software is distributed WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. + + See LICENSE.txt or http://www.mitk.org for details. + + ===================================================================*/ + /* www.sourceforge.net/projects/tinyxml Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #ifndef TINYXML_INCLUDED #define TINYXML_INCLUDED #ifndef TIXML_USE_STL #define TIXML_USE_STL #endif #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable : 4530 ) #pragma warning( disable : 4786 ) #endif #include #include #include #include #include // Help out windows: #if defined( _DEBUG ) && !defined( DEBUG ) -#define DEBUG +#define DEBUG DEBUG #endif #ifdef TIXML_USE_STL - #include - #include - #include - #define TIXML_STRING std::string + #include + #include + #include + #define TIXML_STRING std::string #else - #include "tinystr.h" - #define TIXML_STRING TiXmlString + #include "tinystr.h" + #define TIXML_STRING TiXmlString #endif // Deprecated library function hell. Compilers want to use the // new safe versions. This probably doesn't fully address the problem, // but it gets closer. There are too many compilers for me to fully // test. If you get compilation troubles, undefine TIXML_SAFE #define TIXML_SAFE #ifdef TIXML_SAFE - #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) - // Microsoft visual studio, version 2005 and higher. - #define TIXML_SNPRINTF _snprintf_s - #define TIXML_SSCANF sscanf_s - #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) - // Microsoft visual studio, version 6 and higher. - //#pragma message( "Using _sn* functions." ) - #define TIXML_SNPRINTF _snprintf - #define TIXML_SSCANF sscanf - #elif defined(__GNUC__) && (__GNUC__ >= 3 ) - // GCC version 3 and higher.s - //#warning( "Using sn* functions." ) - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #else - #define TIXML_SNPRINTF snprintf - #define TIXML_SSCANF sscanf - #endif -#endif + #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + // Microsoft visual studio, version 2005 and higher. + #define TIXML_SNPRINTF _snprintf_s + #define TIXML_SSCANF sscanf_s + #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) + // Microsoft visual studio, version 6 and higher. + //#pragma message( "Using _sn* functions." ) + #define TIXML_SNPRINTF _snprintf + #define TIXML_SSCANF sscanf + #elif defined(__GNUC__) && (__GNUC__ >= 3 ) + // GCC version 3 and higher.s + //#warning( "Using sn* functions." ) + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #else + #define TIXML_SNPRINTF snprintf + #define TIXML_SSCANF sscanf + #endif +#endif class TiXmlDocument; class TiXmlElement; class TiXmlComment; class TiXmlUnknown; class TiXmlAttribute; class TiXmlText; class TiXmlDeclaration; class TiXmlParsingData; const int TIXML_MAJOR_VERSION = 2; const int TIXML_MINOR_VERSION = 6; const int TIXML_PATCH_VERSION = 1; -/* Internal structure for tracking location of items - in the XML file. +/* Internal structure for tracking location of items + in the XML file. */ struct TiXmlCursor { - TiXmlCursor() { Clear(); } - void Clear() { row = col = -1; } + TiXmlCursor() { Clear(); } + void Clear() { row = col = -1; } - int row; // 0 based. - int col; // 0 based. + int row; // 0 based. + int col; // 0 based. }; /** - Implements the interface to the "Visitor pattern" (see the Accept() method.) - If you call the Accept() method, it requires being passed a TiXmlVisitor - class to handle callbacks. For nodes that contain other nodes (Document, Element) - you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves - are simply called with Visit(). + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a TiXmlVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves + are simply called with Visit(). - If you return 'true' from a Visit method, recursive parsing will continue. If you return - false, no children of this node or its sibilings will be Visited. + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its sibilings will be Visited. - All flavors of Visit methods have a default implementation that returns 'true' (continue - visiting). You need to only override methods that are interesting to you. + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. - Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. + Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. - You should never change the document from a callback. + You should never change the document from a callback. - @sa TiXmlNode::Accept() + @sa TiXmlNode::Accept() */ class TiXmlVisitor { public: - virtual ~TiXmlVisitor() {} - - /// Visit a document. - virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } - /// Visit a document. - virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } - - /// Visit an element. - virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } - /// Visit an element. - virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } - - /// Visit a declaration - virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } - /// Visit a text node - virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } - /// Visit a comment node - virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } - /// Visit an unknow node - virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } + virtual ~TiXmlVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } + /// Visit a document. + virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } + + /// Visit an element. + virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } + /// Visit an element. + virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } + + /// Visit a declaration + virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } + /// Visit a text node + virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } + /// Visit a comment node + virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } + /// Visit an unknow node + virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } }; // Only used by Attribute::Query functions -enum -{ - TIXML_SUCCESS, - TIXML_NO_ATTRIBUTE, - TIXML_WRONG_TYPE +enum +{ + TIXML_SUCCESS, + TIXML_NO_ATTRIBUTE, + TIXML_WRONG_TYPE }; // Used by the parsing routines. enum TiXmlEncoding { - TIXML_ENCODING_UNKNOWN, - TIXML_ENCODING_UTF8, - TIXML_ENCODING_LEGACY + TIXML_ENCODING_UNKNOWN, + TIXML_ENCODING_UTF8, + TIXML_ENCODING_LEGACY }; const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; /** TiXmlBase is a base class for every class in TinyXml. - It does little except to establish that TinyXml classes - can be printed and provide some utility functions. - - In XML, the document and elements can contain - other elements and other types of nodes. - - @verbatim - A Document can contain: Element (container or leaf) - Comment (leaf) - Unknown (leaf) - Declaration( leaf ) - - An Element can contain: Element (container or leaf) - Text (leaf) - Attributes (not on tree) - Comment (leaf) - Unknown (leaf) - - A Decleration contains: Attributes (not on tree) - @endverbatim + It does little except to establish that TinyXml classes + can be printed and provide some utility functions. + + In XML, the document and elements can contain + other elements and other types of nodes. + + @verbatim + A Document can contain: Element (container or leaf) + Comment (leaf) + Unknown (leaf) + Declaration( leaf ) + + An Element can contain: Element (container or leaf) + Text (leaf) + Attributes (not on tree) + Comment (leaf) + Unknown (leaf) + + A Decleration contains: Attributes (not on tree) + @endverbatim */ class TiXmlBase { - friend class TiXmlNode; - friend class TiXmlElement; - friend class TiXmlDocument; + friend class TiXmlNode; + friend class TiXmlElement; + friend class TiXmlDocument; public: - TiXmlBase() : userData(0) {} - virtual ~TiXmlBase() {} - - /** All TinyXml classes can print themselves to a filestream - or the string class (TiXmlString in non-STL mode, std::string - in STL mode.) Either or both cfile and str can be null. - - This is a formatted print, and will insert - tabs and newlines. - - (For an unformatted stream, use the << operator.) - */ - virtual void Print( FILE* cfile, int depth ) const = 0; - - /** The world does not agree on whether white space should be kept or - not. In order to make everyone happy, these global, static functions - are provided to set whether or not TinyXml will condense all white space - into a single space or not. The default is to condense. Note changing this - value is not thread safe. - */ - static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } - - /// Return the current white space setting. - static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } - - /** Return the position, in the original source file, of this node or attribute. - The row and column are 1-based. (That is the first row and first column is - 1,1). If the returns values are 0 or less, then the parser does not have - a row and column value. - - Generally, the row and column value will be set when the TiXmlDocument::Load(), - TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set - when the DOM was created from operator>>. - - The values reflect the initial load. Once the DOM is modified programmatically - (by adding or changing nodes and attributes) the new values will NOT update to - reflect changes in the document. - - There is a minor performance cost to computing the row and column. Computation - can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. - - @sa TiXmlDocument::SetTabSize() - */ - int Row() const { return location.row + 1; } - int Column() const { return location.col + 1; } ///< See Row() - - void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. - void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. - const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. - - // Table that returs, for a given lead byte, the total number of bytes - // in the UTF-8 sequence. - static const int utf8ByteTable[256]; - - virtual const char* Parse( const char* p, - TiXmlParsingData* data, - TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; - - /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, - or they will be transformed into entities! - */ - static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); - - enum - { - TIXML_NO_ERROR = 0, - TIXML_ERROR, - TIXML_ERROR_OPENING_FILE, - TIXML_ERROR_PARSING_ELEMENT, - TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, - TIXML_ERROR_READING_ELEMENT_VALUE, - TIXML_ERROR_READING_ATTRIBUTES, - TIXML_ERROR_PARSING_EMPTY, - TIXML_ERROR_READING_END_TAG, - TIXML_ERROR_PARSING_UNKNOWN, - TIXML_ERROR_PARSING_COMMENT, - TIXML_ERROR_PARSING_DECLARATION, - TIXML_ERROR_DOCUMENT_EMPTY, - TIXML_ERROR_EMBEDDED_NULL, - TIXML_ERROR_PARSING_CDATA, - TIXML_ERROR_DOCUMENT_TOP_ONLY, - - TIXML_ERROR_STRING_COUNT - }; + TiXmlBase() : userData(0) {} + virtual ~TiXmlBase() {} + + /** All TinyXml classes can print themselves to a filestream + or the string class (TiXmlString in non-STL mode, std::string + in STL mode.) Either or both cfile and str can be null. + + This is a formatted print, and will insert + tabs and newlines. + + (For an unformatted stream, use the << operator.) + */ + virtual void Print( FILE* cfile, int depth ) const = 0; + + /** The world does not agree on whether white space should be kept or + not. In order to make everyone happy, these global, static functions + are provided to set whether or not TinyXml will condense all white space + into a single space or not. The default is to condense. Note changing this + value is not thread safe. + */ + static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } + + /// Return the current white space setting. + static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } + + /** Return the position, in the original source file, of this node or attribute. + The row and column are 1-based. (That is the first row and first column is + 1,1). If the returns values are 0 or less, then the parser does not have + a row and column value. + + Generally, the row and column value will be set when the TiXmlDocument::Load(), + TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set + when the DOM was created from operator>>. + + The values reflect the initial load. Once the DOM is modified programmatically + (by adding or changing nodes and attributes) the new values will NOT update to + reflect changes in the document. + + There is a minor performance cost to computing the row and column. Computation + can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. + + @sa TiXmlDocument::SetTabSize() + */ + int Row() const { return location.row + 1; } + int Column() const { return location.col + 1; } ///< See Row() + + void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. + void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. + const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. + + // Table that returs, for a given lead byte, the total number of bytes + // in the UTF-8 sequence. + static const int utf8ByteTable[256]; + + virtual const char* Parse( const char* p, + TiXmlParsingData* data, + TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; + + /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, + or they will be transformed into entities! + */ + static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); + + enum + { + TIXML_NO_ERROR = 0, + TIXML_ERROR, + TIXML_ERROR_OPENING_FILE, + TIXML_ERROR_PARSING_ELEMENT, + TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, + TIXML_ERROR_READING_ELEMENT_VALUE, + TIXML_ERROR_READING_ATTRIBUTES, + TIXML_ERROR_PARSING_EMPTY, + TIXML_ERROR_READING_END_TAG, + TIXML_ERROR_PARSING_UNKNOWN, + TIXML_ERROR_PARSING_COMMENT, + TIXML_ERROR_PARSING_DECLARATION, + TIXML_ERROR_DOCUMENT_EMPTY, + TIXML_ERROR_EMBEDDED_NULL, + TIXML_ERROR_PARSING_CDATA, + TIXML_ERROR_DOCUMENT_TOP_ONLY, + + TIXML_ERROR_STRING_COUNT + }; protected: - static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); - - inline static bool IsWhiteSpace( char c ) - { - return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); - } - inline static bool IsWhiteSpace( int c ) - { - if ( c < 256 ) - return IsWhiteSpace( (char) c ); - return false; // Again, only truly correct for English/Latin...but usually works. - } - - #ifdef TIXML_USE_STL - static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); - static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); - #endif - - /* Reads an XML name into the string provided. Returns - a pointer just past the last character of the name, - or 0 if the function has an error. - */ - static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); - - /* Reads text. Returns a pointer past the given end tag. - Wickedly complex options, but it keeps the (sensitive) code in one place. - */ - static const char* ReadText( const char* in, // where to start - TIXML_STRING* text, // the string read - bool ignoreWhiteSpace, // whether to keep the white space - const char* endTag, // what ends this text - bool ignoreCase, // whether to ignore case in the end tag - TiXmlEncoding encoding ); // the current encoding - - // If an entity has been found, transform it into a character. - static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); - - // Get a character, while interpreting entities. - // The length can be from 0 to 4 bytes. - inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) - { - assert( p ); - if ( encoding == TIXML_ENCODING_UTF8 ) - { - *length = utf8ByteTable[ *((const unsigned char*)p) ]; - assert( *length >= 0 && *length < 5 ); - } - else - { - *length = 1; - } - - if ( *length == 1 ) - { - if ( *p == '&' ) - return GetEntity( p, _value, length, encoding ); - *_value = *p; - return p+1; - } - else if ( *length ) - { - //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), - // and the null terminator isn't needed - for( int i=0; p[i] && i<*length; ++i ) { - _value[i] = p[i]; - } - return p + (*length); - } - else - { - // Not valid text. - return 0; - } - } - - // Return true if the next characters in the stream are any of the endTag sequences. - // Ignore case only works for english, and should only be relied on when comparing - // to English words: StringEqual( p, "version", true ) is fine. - static bool StringEqual( const char* p, - const char* endTag, - bool ignoreCase, - TiXmlEncoding encoding ); - - static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; - - TiXmlCursor location; + static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); + + inline static bool IsWhiteSpace( char c ) + { + return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); + } + inline static bool IsWhiteSpace( int c ) + { + if ( c < 256 ) + return IsWhiteSpace( (char) c ); + return false; // Again, only truly correct for English/Latin...but usually works. + } + + #ifdef TIXML_USE_STL + static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); + static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); + #endif + + /* Reads an XML name into the string provided. Returns + a pointer just past the last character of the name, + or 0 if the function has an error. + */ + static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); + + /* Reads text. Returns a pointer past the given end tag. + Wickedly complex options, but it keeps the (sensitive) code in one place. + */ + static const char* ReadText( const char* in, // where to start + TIXML_STRING* text, // the string read + bool ignoreWhiteSpace, // whether to keep the white space + const char* endTag, // what ends this text + bool ignoreCase, // whether to ignore case in the end tag + TiXmlEncoding encoding ); // the current encoding + + // If an entity has been found, transform it into a character. + static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); + + // Get a character, while interpreting entities. + // The length can be from 0 to 4 bytes. + inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) + { + assert( p ); + if ( encoding == TIXML_ENCODING_UTF8 ) + { + *length = utf8ByteTable[ *((const unsigned char*)p) ]; + assert( *length >= 0 && *length < 5 ); + } + else + { + *length = 1; + } + + if ( *length == 1 ) + { + if ( *p == '&' ) + return GetEntity( p, _value, length, encoding ); + *_value = *p; + return p+1; + } + else if ( *length ) + { + //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), + // and the null terminator isn't needed + for( int i=0; p[i] && i<*length; ++i ) { + _value[i] = p[i]; + } + return p + (*length); + } + else + { + // Not valid text. + return 0; + } + } + + // Return true if the next characters in the stream are any of the endTag sequences. + // Ignore case only works for english, and should only be relied on when comparing + // to English words: StringEqual( p, "version", true ) is fine. + static bool StringEqual( const char* p, + const char* endTag, + bool ignoreCase, + TiXmlEncoding encoding ); + + static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; + + TiXmlCursor location; /// Field containing a generic user pointer - void* userData; - - // None of these methods are reliable for any language except English. - // Good for approximation, not great for accuracy. - static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); - static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); - inline static int ToLower( int v, TiXmlEncoding encoding ) - { - if ( encoding == TIXML_ENCODING_UTF8 ) - { - if ( v < 128 ) return tolower( v ); - return v; - } - else - { - return tolower( v ); - } - } - static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); + void* userData; + + // None of these methods are reliable for any language except English. + // Good for approximation, not great for accuracy. + static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); + static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); + inline static int ToLower( int v, TiXmlEncoding encoding ) + { + if ( encoding == TIXML_ENCODING_UTF8 ) + { + if ( v < 128 ) return tolower( v ); + return v; + } + else + { + return tolower( v ); + } + } + static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); private: - TiXmlBase( const TiXmlBase& ); // not implemented. - void operator=( const TiXmlBase& base ); // not allowed. - - struct Entity - { - const char* str; - unsigned int strLength; - char chr; - }; - enum - { - NUM_ENTITY = 5, - MAX_ENTITY_LENGTH = 6 - - }; - static Entity entity[ NUM_ENTITY ]; - static bool condenseWhiteSpace; + TiXmlBase( const TiXmlBase& ); // not implemented. + void operator=( const TiXmlBase& base ); // not allowed. + + struct Entity + { + const char* str; + unsigned int strLength; + char chr; + }; + enum + { + NUM_ENTITY = 5, + MAX_ENTITY_LENGTH = 6 + + }; + static Entity entity[ NUM_ENTITY ]; + static bool condenseWhiteSpace; }; /** The parent class for everything in the Document Object Model. - (Except for attributes). - Nodes have siblings, a parent, and children. A node can be - in a document, or stand on its own. The type of a TiXmlNode - can be queried, and it can be cast to its more defined type. + (Except for attributes). + Nodes have siblings, a parent, and children. A node can be + in a document, or stand on its own. The type of a TiXmlNode + can be queried, and it can be cast to its more defined type. */ class TiXmlNode : public TiXmlBase { - friend class TiXmlDocument; - friend class TiXmlElement; + friend class TiXmlDocument; + friend class TiXmlElement; public: - #ifdef TIXML_USE_STL - - /** An input stream operator, for every class. Tolerant of newlines and - formatting, but doesn't expect them. - */ - friend std::istream& operator >> (std::istream& in, TiXmlNode& base); - - /** An output stream operator, for every class. Note that this outputs - without any newlines or formatting, as opposed to Print(), which - includes tabs and new lines. - - The operator<< and operator>> are not completely symmetric. Writing - a node to a stream is very well defined. You'll get a nice stream - of output, without any extra whitespace or newlines. - - But reading is not as well defined. (As it always is.) If you create - a TiXmlElement (for example) and read that from an input stream, - the text needs to define an element or junk will result. This is - true of all input streams, but it's worth keeping in mind. - - A TiXmlDocument will read nodes until it reads a root element, and - all the children of that root element. - */ - friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); - - /// Appends the XML node or attribute to a std::string. - friend std::string& operator<< (std::string& out, const TiXmlNode& base ); - - #endif - - /** The types of XML nodes supported by TinyXml. (All the - unsupported types are picked up by UNKNOWN.) - */ - enum NodeType - { - TINYXML_DOCUMENT, - TINYXML_ELEMENT, - TINYXML_COMMENT, - TINYXML_UNKNOWN, - TINYXML_TEXT, - TINYXML_DECLARATION, - TINYXML_TYPECOUNT - }; - - virtual ~TiXmlNode(); - - /** The meaning of 'value' changes for the specific type of - TiXmlNode. - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - - The subclasses will wrap this function. - */ - const char *Value() const { return value.c_str (); } + #ifdef TIXML_USE_STL + + /** An input stream operator, for every class. Tolerant of newlines and + formatting, but doesn't expect them. + */ + friend std::istream& operator >> (std::istream& in, TiXmlNode& base); + + /** An output stream operator, for every class. Note that this outputs + without any newlines or formatting, as opposed to Print(), which + includes tabs and new lines. + + The operator<< and operator>> are not completely symmetric. Writing + a node to a stream is very well defined. You'll get a nice stream + of output, without any extra whitespace or newlines. + + But reading is not as well defined. (As it always is.) If you create + a TiXmlElement (for example) and read that from an input stream, + the text needs to define an element or junk will result. This is + true of all input streams, but it's worth keeping in mind. + + A TiXmlDocument will read nodes until it reads a root element, and + all the children of that root element. + */ + friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); + + /// Appends the XML node or attribute to a std::string. + friend std::string& operator<< (std::string& out, const TiXmlNode& base ); + + #endif + + /** The types of XML nodes supported by TinyXml. (All the + unsupported types are picked up by UNKNOWN.) + */ + enum NodeType + { + TINYXML_DOCUMENT, + TINYXML_ELEMENT, + TINYXML_COMMENT, + TINYXML_UNKNOWN, + TINYXML_TEXT, + TINYXML_DECLARATION, + TINYXML_TYPECOUNT + }; + + virtual ~TiXmlNode(); + + /** The meaning of 'value' changes for the specific type of + TiXmlNode. + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + + The subclasses will wrap this function. + */ + const char *Value() const { return value.c_str (); } #ifdef TIXML_USE_STL - /** Return Value() as a std::string. If you only use STL, - this is more efficient than calling Value(). - Only available in STL mode. - */ - const std::string& ValueStr() const { return value; } - #endif - - const TIXML_STRING& ValueTStr() const { return value; } - - /** Changes the value of the node. Defined as: - @verbatim - Document: filename of the xml file - Element: name of the element - Comment: the comment text - Unknown: the tag contents - Text: the text string - @endverbatim - */ - void SetValue(const char * _value) { value = _value;} + /** Return Value() as a std::string. If you only use STL, + this is more efficient than calling Value(). + Only available in STL mode. + */ + const std::string& ValueStr() const { return value; } + #endif + + const TIXML_STRING& ValueTStr() const { return value; } + + /** Changes the value of the node. Defined as: + @verbatim + Document: filename of the xml file + Element: name of the element + Comment: the comment text + Unknown: the tag contents + Text: the text string + @endverbatim + */ + void SetValue(const char * _value) { value = _value;} #ifdef TIXML_USE_STL - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Delete all the children of this node. Does not affect 'this'. - void Clear(); - - /// One step up the DOM. - TiXmlNode* Parent() { return parent; } - const TiXmlNode* Parent() const { return parent; } - - const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. - TiXmlNode* FirstChild() { return firstChild; } - const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. - /// The first child of this node with the matching 'value'. Will be null if none found. - TiXmlNode* FirstChild( const char * _value ) { - // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) - // call the method, cast the return back to non-const. - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); - } - const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. - TiXmlNode* LastChild() { return lastChild; } - - const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. - TiXmlNode* LastChild( const char * _value ) { - return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); - } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Delete all the children of this node. Does not affect 'this'. + void Clear(); + + /// One step up the DOM. + TiXmlNode* Parent() { return parent; } + const TiXmlNode* Parent() const { return parent; } + + const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. + TiXmlNode* FirstChild() { return firstChild; } + const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. + /// The first child of this node with the matching 'value'. Will be null if none found. + TiXmlNode* FirstChild( const char * _value ) { + // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) + // call the method, cast the return back to non-const. + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); + } + const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. + TiXmlNode* LastChild() { return lastChild; } + + const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. + TiXmlNode* LastChild( const char * _value ) { + return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); + } #ifdef TIXML_USE_STL - const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. - #endif - - /** An alternate way to walk the children of a node. - One way to iterate over nodes is: - @verbatim - for( child = parent->FirstChild(); child; child = child->NextSibling() ) - @endverbatim - - IterateChildren does the same thing with the syntax: - @verbatim - child = 0; - while( child = parent->IterateChildren( child ) ) - @endverbatim - - IterateChildren takes the previous child as input and finds - the next one. If the previous child is null, it returns the - first. IterateChildren will return null when done. - */ - const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); - } - - /// This flavor of IterateChildren searches for children with a particular 'value' - const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; - TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); - } + const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. + #endif + + /** An alternate way to walk the children of a node. + One way to iterate over nodes is: + @verbatim + for( child = parent->FirstChild(); child; child = child->NextSibling() ) + @endverbatim + + IterateChildren does the same thing with the syntax: + @verbatim + child = 0; + while( child = parent->IterateChildren( child ) ) + @endverbatim + + IterateChildren takes the previous child as input and finds + the next one. If the previous child is null, it returns the + first. IterateChildren will return null when done. + */ + const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); + } + + /// This flavor of IterateChildren searches for children with a particular 'value' + const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; + TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); + } #ifdef TIXML_USE_STL - const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. - #endif + const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. + #endif - /** Add a new node related to this. Adds a child past the LastChild. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); + /** Add a new node related to this. Adds a child past the LastChild. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); - /** Add a new node related to this. Adds a child past the LastChild. + /** Add a new node related to this. Adds a child past the LastChild. - NOTE: the node to be added is passed by pointer, and will be - henceforth owned (and deleted) by tinyXml. This method is efficient - and avoids an extra copy, but should be used with care as it - uses a different memory model than the other insert functions. + NOTE: the node to be added is passed by pointer, and will be + henceforth owned (and deleted) by tinyXml. This method is efficient + and avoids an extra copy, but should be used with care as it + uses a different memory model than the other insert functions. - @sa InsertEndChild - */ - TiXmlNode* LinkEndChild( TiXmlNode* addThis ); + @sa InsertEndChild + */ + TiXmlNode* LinkEndChild( TiXmlNode* addThis ); - /** Add a new node related to this. Adds a child before the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); + /** Add a new node related to this. Adds a child before the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); - /** Add a new node related to this. Adds a child after the specified child. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); + /** Add a new node related to this. Adds a child after the specified child. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); - /** Replace a child of this node. - Returns a pointer to the new object or NULL if an error occured. - */ - TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); + /** Replace a child of this node. + Returns a pointer to the new object or NULL if an error occured. + */ + TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); - /// Delete a child of this node. - bool RemoveChild( TiXmlNode* removeThis ); + /// Delete a child of this node. + bool RemoveChild( TiXmlNode* removeThis ); - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling() const { return prev; } - TiXmlNode* PreviousSibling() { return prev; } + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling() const { return prev; } + TiXmlNode* PreviousSibling() { return prev; } - /// Navigate to a sibling node. - const TiXmlNode* PreviousSibling( const char * ) const; - TiXmlNode* PreviousSibling( const char *_prev ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); - } + /// Navigate to a sibling node. + const TiXmlNode* PreviousSibling( const char * ) const; + TiXmlNode* PreviousSibling( const char *_prev ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); + } #ifdef TIXML_USE_STL - const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. - const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. - TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Navigate to a sibling node. - const TiXmlNode* NextSibling() const { return next; } - TiXmlNode* NextSibling() { return next; } - - /// Navigate to a sibling node with the given 'value'. - const TiXmlNode* NextSibling( const char * ) const; - TiXmlNode* NextSibling( const char* _next ) { - return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement() const; - TiXmlElement* NextSiblingElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); - } - - /** Convenience function to get through elements. - Calls NextSibling and ToElement. Will skip all non-Element - nodes. Returns 0 if there is not another element. - */ - const TiXmlElement* NextSiblingElement( const char * ) const; - TiXmlElement* NextSiblingElement( const char *_next ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); - } + const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. + const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. + TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Navigate to a sibling node. + const TiXmlNode* NextSibling() const { return next; } + TiXmlNode* NextSibling() { return next; } + + /// Navigate to a sibling node with the given 'value'. + const TiXmlNode* NextSibling( const char * ) const; + TiXmlNode* NextSibling( const char* _next ) { + return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement() const; + TiXmlElement* NextSiblingElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); + } + + /** Convenience function to get through elements. + Calls NextSibling and ToElement. Will skip all non-Element + nodes. Returns 0 if there is not another element. + */ + const TiXmlElement* NextSiblingElement( const char * ) const; + TiXmlElement* NextSiblingElement( const char *_next ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); + } #ifdef TIXML_USE_STL - const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement() const; - TiXmlElement* FirstChildElement() { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); - } - - /// Convenience function to get through elements. - const TiXmlElement* FirstChildElement( const char * _value ) const; - TiXmlElement* FirstChildElement( const char * _value ) { - return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); - } + const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement() const; + TiXmlElement* FirstChildElement() { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); + } + + /// Convenience function to get through elements. + const TiXmlElement* FirstChildElement( const char * _value ) const; + TiXmlElement* FirstChildElement( const char * _value ) { + return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); + } #ifdef TIXML_USE_STL - const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. - #endif - - /** Query the type (as an enumerated value, above) of this node. - The possible types are: DOCUMENT, ELEMENT, COMMENT, - UNKNOWN, TEXT, and DECLARATION. - */ - int Type() const { return type; } - - /** Return a pointer to the Document this node lives in. - Returns null if not in a document. - */ - const TiXmlDocument* GetDocument() const; - TiXmlDocument* GetDocument() { - return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); - } - - /// Returns true if this node has no children. - bool NoChildren() const { return !firstChild; } - - virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. - - /** Create an exact duplicate of this node and return it. The memory must be deleted - by the caller. - */ - virtual TiXmlNode* Clone() const = 0; - - /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the - XML tree will be conditionally visited and the host will be called back - via the TiXmlVisitor interface. - - This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse - the XML for the callbacks, so the performance of TinyXML is unchanged by using this - interface versus any other.) - - The interface has been based on ideas from: - - - http://www.saxproject.org/ - - http://c2.com/cgi/wiki?HierarchicalVisitorPattern - - Which are both good references for "visiting". - - An example of using Accept(): - @verbatim - TiXmlPrinter printer; - tinyxmlDoc.Accept( &printer ); - const char* xmlcstr = printer.CStr(); - @endverbatim - */ - virtual bool Accept( TiXmlVisitor* visitor ) const = 0; + const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. + #endif + + /** Query the type (as an enumerated value, above) of this node. + The possible types are: DOCUMENT, ELEMENT, COMMENT, + UNKNOWN, TEXT, and DECLARATION. + */ + int Type() const { return type; } + + /** Return a pointer to the Document this node lives in. + Returns null if not in a document. + */ + const TiXmlDocument* GetDocument() const; + TiXmlDocument* GetDocument() { + return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); + } + + /// Returns true if this node has no children. + bool NoChildren() const { return !firstChild; } + + virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. + + /** Create an exact duplicate of this node and return it. The memory must be deleted + by the caller. + */ + virtual TiXmlNode* Clone() const = 0; + + /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the TiXmlVisitor interface. + + This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + TiXmlPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( TiXmlVisitor* visitor ) const = 0; protected: - TiXmlNode( NodeType _type ); + TiXmlNode( NodeType _type ); - // Copy to the allocated object. Shared functionality between Clone, Copy constructor, - // and the assignment operator. - void CopyTo( TiXmlNode* target ) const; + // Copy to the allocated object. Shared functionality between Clone, Copy constructor, + // and the assignment operator. + void CopyTo( TiXmlNode* target ) const; - #ifdef TIXML_USE_STL - // The real work of the input operator. - virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; - #endif + #ifdef TIXML_USE_STL + // The real work of the input operator. + virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; + #endif - // Figure out what is at *p, and parse it. Returns null if it is not an xml node. - TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); + // Figure out what is at *p, and parse it. Returns null if it is not an xml node. + TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); - TiXmlNode* parent; - NodeType type; + TiXmlNode* parent; + NodeType type; - TiXmlNode* firstChild; - TiXmlNode* lastChild; + TiXmlNode* firstChild; + TiXmlNode* lastChild; - TIXML_STRING value; + TIXML_STRING value; - TiXmlNode* prev; - TiXmlNode* next; + TiXmlNode* prev; + TiXmlNode* next; private: - TiXmlNode( const TiXmlNode& ); // not implemented. - void operator=( const TiXmlNode& base ); // not allowed. + TiXmlNode( const TiXmlNode& ); // not implemented. + void operator=( const TiXmlNode& base ); // not allowed. }; /** An attribute is a name-value pair. Elements have an arbitrary - number of attributes, each with a unique name. + number of attributes, each with a unique name. - @note The attributes are not TiXmlNodes, since they are not - part of the tinyXML document object model. There are other - suggested ways to look at this problem. + @note The attributes are not TiXmlNodes, since they are not + part of the tinyXML document object model. There are other + suggested ways to look at this problem. */ class TiXmlAttribute : public TiXmlBase { - friend class TiXmlAttributeSet; + friend class TiXmlAttributeSet; public: - /// Construct an empty attribute. - TiXmlAttribute() : TiXmlBase() - { - document = 0; - prev = next = 0; - } - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlAttribute( const std::string& _name, const std::string& _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - #endif - - /// Construct an attribute with a name and value. - TiXmlAttribute( const char * _name, const char * _value ) - { - name = _name; - value = _value; - document = 0; - prev = next = 0; - } - - const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. - const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. - #ifdef TIXML_USE_STL - const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. - #endif - int IntValue() const; ///< Return the value of this attribute, converted to an integer. - double DoubleValue() const; ///< Return the value of this attribute, converted to a double. - - // Get the tinyxml string representation - const TIXML_STRING& NameTStr() const { return name; } - - /** QueryIntValue examines the value string. It is an alternative to the - IntValue() method with richer error checking. - If the value is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. - - A specialized but useful call. Note that for success it returns 0, - which is the opposite of almost all other TinyXml calls. - */ - int QueryIntValue( int* _value ) const; - /// QueryDoubleValue examines the value string. See QueryIntValue(). - int QueryDoubleValue( double* _value ) const; - - void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. - void SetValue( const char* _value ) { value = _value; } ///< Set the value. - - void SetIntValue( int _value ); ///< Set the value from an integer. - void SetDoubleValue( double _value ); ///< Set the value from a double. + /// Construct an empty attribute. + TiXmlAttribute() : TiXmlBase() + { + document = 0; + prev = next = 0; + } + + #ifdef TIXML_USE_STL + /// std::string constructor. + TiXmlAttribute( const std::string& _name, const std::string& _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + #endif + + /// Construct an attribute with a name and value. + TiXmlAttribute( const char * _name, const char * _value ) + { + name = _name; + value = _value; + document = 0; + prev = next = 0; + } + + const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. + const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. + #ifdef TIXML_USE_STL + const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. + #endif + int IntValue() const; ///< Return the value of this attribute, converted to an integer. + double DoubleValue() const; ///< Return the value of this attribute, converted to a double. + + // Get the tinyxml string representation + const TIXML_STRING& NameTStr() const { return name; } + + /** QueryIntValue examines the value string. It is an alternative to the + IntValue() method with richer error checking. + If the value is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. + + A specialized but useful call. Note that for success it returns 0, + which is the opposite of almost all other TinyXml calls. + */ + int QueryIntValue( int* _value ) const; + /// QueryDoubleValue examines the value string. See QueryIntValue(). + int QueryDoubleValue( double* _value ) const; + + void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. + void SetValue( const char* _value ) { value = _value; } ///< Set the value. + + void SetIntValue( int _value ); ///< Set the value from an integer. + void SetDoubleValue( double _value ); ///< Set the value from a double. #ifdef TIXML_USE_STL - /// STL std::string form. - void SetName( const std::string& _name ) { name = _name; } - /// STL std::string form. - void SetValue( const std::string& _value ) { value = _value; } - #endif - - /// Get the next sibling attribute in the DOM. Returns null at end. - const TiXmlAttribute* Next() const; - TiXmlAttribute* Next() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); - } - - /// Get the previous sibling attribute in the DOM. Returns null at beginning. - const TiXmlAttribute* Previous() const; - TiXmlAttribute* Previous() { - return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); - } - - bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } - bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } - bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } - - /* Attribute parsing starts: first letter of the name - returns: the next char after the value end quote - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - // Prints this Attribute to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } - void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - - // [internal use] - // Set the document pointer so the attribute can report errors. - void SetDocument( TiXmlDocument* doc ) { document = doc; } + /// STL std::string form. + void SetName( const std::string& _name ) { name = _name; } + /// STL std::string form. + void SetValue( const std::string& _value ) { value = _value; } + #endif + + /// Get the next sibling attribute in the DOM. Returns null at end. + const TiXmlAttribute* Next() const; + TiXmlAttribute* Next() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); + } + + /// Get the previous sibling attribute in the DOM. Returns null at beginning. + const TiXmlAttribute* Previous() const; + TiXmlAttribute* Previous() { + return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); + } + + bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } + bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } + bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } + + /* Attribute parsing starts: first letter of the name + returns: the next char after the value end quote + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + // Prints this Attribute to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } + void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + + // [internal use] + // Set the document pointer so the attribute can report errors. + void SetDocument( TiXmlDocument* doc ) { document = doc; } private: - TiXmlAttribute( const TiXmlAttribute& ); // not implemented. - void operator=( const TiXmlAttribute& base ); // not allowed. - - TiXmlDocument* document; // A pointer back to a document, for error reporting. - TIXML_STRING name; - TIXML_STRING value; - TiXmlAttribute* prev; - TiXmlAttribute* next; + TiXmlAttribute( const TiXmlAttribute& ); // not implemented. + void operator=( const TiXmlAttribute& base ); // not allowed. + + TiXmlDocument* document; // A pointer back to a document, for error reporting. + TIXML_STRING name; + TIXML_STRING value; + TiXmlAttribute* prev; + TiXmlAttribute* next; }; -/* A class used to manage a group of attributes. - It is only used internally, both by the ELEMENT and the DECLARATION. - - The set can be changed transparent to the Element and Declaration - classes that use it, but NOT transparent to the Attribute - which has to implement a next() and previous() method. Which makes - it a bit problematic and prevents the use of STL. +/* A class used to manage a group of attributes. + It is only used internally, both by the ELEMENT and the DECLARATION. + + The set can be changed transparent to the Element and Declaration + classes that use it, but NOT transparent to the Attribute + which has to implement a next() and previous() method. Which makes + it a bit problematic and prevents the use of STL. - This version is implemented with circular lists because: - - I like circular lists - - it demonstrates some independence from the (typical) doubly linked list. + This version is implemented with circular lists because: + - I like circular lists + - it demonstrates some independence from the (typical) doubly linked list. */ class TiXmlAttributeSet { public: - TiXmlAttributeSet(); - ~TiXmlAttributeSet(); + TiXmlAttributeSet(); + ~TiXmlAttributeSet(); - void Add( TiXmlAttribute* attribute ); - void Remove( TiXmlAttribute* attribute ); + void Add( TiXmlAttribute* attribute ); + void Remove( TiXmlAttribute* attribute ); - const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } - const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } + const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } + TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } - TiXmlAttribute* Find( const char* _name ) const; - TiXmlAttribute* FindOrCreate( const char* _name ); + TiXmlAttribute* Find( const char* _name ) const; + TiXmlAttribute* FindOrCreate( const char* _name ); -# ifdef TIXML_USE_STL - TiXmlAttribute* Find( const std::string& _name ) const; - TiXmlAttribute* FindOrCreate( const std::string& _name ); -# endif +# ifdef TIXML_USE_STL + TiXmlAttribute* Find( const std::string& _name ) const; + TiXmlAttribute* FindOrCreate( const std::string& _name ); +# endif private: - //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), - //*ME: this class must be also use a hidden/disabled copy-constructor !!! - TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed - void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) + //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), + //*ME: this class must be also use a hidden/disabled copy-constructor !!! + TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed + void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) - TiXmlAttribute sentinel; + TiXmlAttribute sentinel; }; /** The element is a container class. It has a value, the element name, - and can contain other elements, text, comments, and unknowns. - Elements also contain an arbitrary number of attributes. + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. */ class TiXmlElement : public TiXmlNode { public: - /// Construct an element. - TiXmlElement (const char * in_value); - - #ifdef TIXML_USE_STL - /// std::string constructor. - TiXmlElement( const std::string& _value ); - #endif - - TiXmlElement( const TiXmlElement& ); - - void operator=( const TiXmlElement& base ); - - virtual ~TiXmlElement(); - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - */ - const char* Attribute( const char* name ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an integer, - the integer value will be put in the return 'i', if 'i' - is non-null. - */ - const char* Attribute( const char* name, int* i ) const; - - /** Given an attribute name, Attribute() returns the value - for the attribute of that name, or null if none exists. - If the attribute exists and can be converted to an double, - the double value will be put in the return 'd', if 'd' - is non-null. - */ - const char* Attribute( const char* name, double* d ) const; - - /** QueryIntAttribute examines the attribute - it is an alternative to the - Attribute() method with richer error checking. - If the attribute is an integer, it is stored in 'value' and - the call returns TIXML_SUCCESS. If it is not - an integer, it returns TIXML_WRONG_TYPE. If the attribute - does not exist, then TIXML_NO_ATTRIBUTE is returned. - */ - int QueryIntAttribute( const char* name, int* _value ) const; - /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). - int QueryDoubleAttribute( const char* name, double* _value ) const; - /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). - int QueryFloatAttribute( const char* name, float* _value ) const { - double d; - int result = QueryDoubleAttribute( name, &d ); - if ( result == TIXML_SUCCESS ) { - *_value = (float)d; - } - return result; - } + /// Construct an element. + TiXmlElement (const char * in_value); #ifdef TIXML_USE_STL - /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). - int QueryStringAttribute( const char* name, std::string* _value ) const { - const char* cstr = Attribute( name ); - if ( cstr ) { - *_value = std::string( cstr ); - return TIXML_SUCCESS; - } - return TIXML_NO_ATTRIBUTE; - } - - /** Template form of the attribute query which will try to read the - attribute into the specified type. Very easy, very powerful, but - be careful to make sure to call this with the correct type. - - NOTE: This method doesn't work correctly for 'string' types that contain spaces. - - @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE - */ - template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - - std::stringstream sstream( node->ValueStr() ); - sstream >> *outValue; - if ( !sstream.fail() ) - return TIXML_SUCCESS; - return TIXML_WRONG_TYPE; - } - - int QueryValueAttribute( const std::string& name, std::string* outValue ) const - { - const TiXmlAttribute* node = attributeSet.Find( name ); - if ( !node ) - return TIXML_NO_ATTRIBUTE; - *outValue = node->ValueStr(); - return TIXML_SUCCESS; - } - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char* name, const char * _value ); + /// std::string constructor. + TiXmlElement( const std::string& _value ); + #endif + + TiXmlElement( const TiXmlElement& ); + + void operator=( const TiXmlElement& base ); + + virtual ~TiXmlElement(); + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + */ + const char* Attribute( const char* name ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an integer, + the integer value will be put in the return 'i', if 'i' + is non-null. + */ + const char* Attribute( const char* name, int* i ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none exists. + If the attribute exists and can be converted to an double, + the double value will be put in the return 'd', if 'd' + is non-null. + */ + const char* Attribute( const char* name, double* d ) const; + + /** QueryIntAttribute examines the attribute - it is an alternative to the + Attribute() method with richer error checking. + If the attribute is an integer, it is stored in 'value' and + the call returns TIXML_SUCCESS. If it is not + an integer, it returns TIXML_WRONG_TYPE. If the attribute + does not exist, then TIXML_NO_ATTRIBUTE is returned. + */ + int QueryIntAttribute( const char* name, int* _value ) const; + /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). + int QueryDoubleAttribute( const char* name, double* _value ) const; + /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). + int QueryFloatAttribute( const char* name, float* _value ) const { + double d; + int result = QueryDoubleAttribute( name, &d ); + if ( result == TIXML_SUCCESS ) { + *_value = (float)d; + } + return result; + } #ifdef TIXML_USE_STL - const std::string* Attribute( const std::string& name ) const; - const std::string* Attribute( const std::string& name, int* i ) const; - const std::string* Attribute( const std::string& name, double* d ) const; - int QueryIntAttribute( const std::string& name, int* _value ) const; - int QueryDoubleAttribute( const std::string& name, double* _value ) const; - - /// STL std::string form. - void SetAttribute( const std::string& name, const std::string& _value ); - ///< STL std::string form. - void SetAttribute( const std::string& name, int _value ); - ///< STL std::string form. - void SetDoubleAttribute( const std::string& name, double value ); - #endif - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetAttribute( const char * name, int value ); - - /** Sets an attribute of name to a given value. The attribute - will be created if it does not exist, or changed if it does. - */ - void SetDoubleAttribute( const char * name, double value ); - - /** Deletes an attribute with the given name. - */ - void RemoveAttribute( const char * name ); + /// QueryStringAttribute examines the attribute - see QueryIntAttribute(). + int QueryStringAttribute( const char* name, std::string* _value ) const { + const char* cstr = Attribute( name ); + if ( cstr ) { + *_value = std::string( cstr ); + return TIXML_SUCCESS; + } + return TIXML_NO_ATTRIBUTE; + } + + /** Template form of the attribute query which will try to read the + attribute into the specified type. Very easy, very powerful, but + be careful to make sure to call this with the correct type. + + NOTE: This method doesn't work correctly for 'string' types that contain spaces. + + @return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE + */ + template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + + std::stringstream sstream( node->ValueStr() ); + sstream >> *outValue; + if ( !sstream.fail() ) + return TIXML_SUCCESS; + return TIXML_WRONG_TYPE; + } + + int QueryValueAttribute( const std::string& name, std::string* outValue ) const + { + const TiXmlAttribute* node = attributeSet.Find( name ); + if ( !node ) + return TIXML_NO_ATTRIBUTE; + *outValue = node->ValueStr(); + return TIXML_SUCCESS; + } + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char* name, const char * _value ); + #ifdef TIXML_USE_STL - void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. - #endif - - const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. - TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } - const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. - TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } - - /** Convenience function for easy access to the text inside an element. Although easy - and concise, GetText() is limited compared to getting the TiXmlText child - and accessing it directly. - - If the first child of 'this' is a TiXmlText, the GetText() - returns the character string of the Text node, else null is returned. - - This is a convenient method for getting the text of simple contained text: - @verbatim - This is text - const char* str = fooElement->GetText(); - @endverbatim - - 'str' will be a pointer to "This is text". - - Note that this function can be misleading. If the element foo was created from - this XML: - @verbatim - This is text - @endverbatim - - then the value of str would be null. The first child node isn't a text node, it is - another element. From this XML: - @verbatim - This is text - @endverbatim - GetText() will return "This is ". - - WARNING: GetText() accesses a child node - don't become confused with the - similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are - safe type casts on the referenced node. - */ - const char* GetText() const; - - /// Creates a new Element and returns it - the returned element is a copy. - virtual TiXmlNode* Clone() const; - // Print the Element to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: next char past '<' - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; + const std::string* Attribute( const std::string& name ) const; + const std::string* Attribute( const std::string& name, int* i ) const; + const std::string* Attribute( const std::string& name, double* d ) const; + int QueryIntAttribute( const std::string& name, int* _value ) const; + int QueryDoubleAttribute( const std::string& name, double* _value ) const; + + /// STL std::string form. + void SetAttribute( const std::string& name, const std::string& _value ); + ///< STL std::string form. + void SetAttribute( const std::string& name, int _value ); + ///< STL std::string form. + void SetDoubleAttribute( const std::string& name, double value ); + #endif + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetAttribute( const char * name, int value ); + + /** Sets an attribute of name to a given value. The attribute + will be created if it does not exist, or changed if it does. + */ + void SetDoubleAttribute( const char * name, double value ); + + /** Deletes an attribute with the given name. + */ + void RemoveAttribute( const char * name ); + #ifdef TIXML_USE_STL + void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. + #endif + + const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. + TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } + const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. + TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the TiXmlText child + and accessing it directly. + + If the first child of 'this' is a TiXmlText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + + WARNING: GetText() accesses a child node - don't become confused with the + similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are + safe type casts on the referenced node. + */ + const char* GetText() const; + + /// Creates a new Element and returns it - the returned element is a copy. + virtual TiXmlNode* Clone() const; + // Print the Element to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: next char past '<' + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; protected: - void CopyTo( TiXmlElement* target ) const; - void ClearThis(); // like clear, but initializes 'this' object as well + void CopyTo( TiXmlElement* target ) const; + void ClearThis(); // like clear, but initializes 'this' object as well - // Used to be public [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif - /* [internal use] - Reads the "value" of the element -- another element, or text. - This should terminate with the current end tag. - */ - const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + // Used to be public [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif + /* [internal use] + Reads the "value" of the element -- another element, or text. + This should terminate with the current end tag. + */ + const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); private: - TiXmlAttributeSet attributeSet; + TiXmlAttributeSet attributeSet; }; -/** An XML comment. +/** An XML comment. */ class TiXmlComment : public TiXmlNode { public: - /// Constructs an empty comment. - TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} - /// Construct a comment from text. - TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { - SetValue( _value ); - } - TiXmlComment( const TiXmlComment& ); - void operator=( const TiXmlComment& base ); - - virtual ~TiXmlComment() {} - - /// Returns a copy of this Comment. - virtual TiXmlNode* Clone() const; - // Write this Comment to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /* Attribtue parsing starts: at the ! of the !-- - returns: next char past '>' - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; + /// Constructs an empty comment. + TiXmlComment() : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) {} + /// Construct a comment from text. + TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::TINYXML_COMMENT ) { + SetValue( _value ); + } + TiXmlComment( const TiXmlComment& ); + void operator=( const TiXmlComment& base ); + + virtual ~TiXmlComment() {} + + /// Returns a copy of this Comment. + virtual TiXmlNode* Clone() const; + // Write this Comment to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /* Attribtue parsing starts: at the ! of the !-- + returns: next char past '>' + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; protected: - void CopyTo( TiXmlComment* target ) const; + void CopyTo( TiXmlComment* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif -// virtual void StreamOut( TIXML_OSTREAM * out ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif +// virtual void StreamOut( TIXML_OSTREAM * out ) const; private: }; -/** XML text. A text node can have 2 ways to output the next. "normal" output - and CDATA. It will default to the mode it was parsed from the XML file and - you generally want to leave it alone, but you can change the output mode with - SetCDATA() and query it with CDATA(). +/** XML text. A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCDATA() and query it with CDATA(). */ class TiXmlText : public TiXmlNode { - friend class TiXmlElement; + friend class TiXmlElement; public: - /** Constructor for text element. By default, it is treated as - normal, encoded text. If you want it be output as a CDATA text - element, set the parameter _cdata to 'true' - */ - TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - virtual ~TiXmlText() {} - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) - { - SetValue( initValue ); - cdata = false; - } - #endif - - TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } - void operator=( const TiXmlText& base ) { base.CopyTo( this ); } - - // Write this text object to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; - - /// Queries whether this represents text using a CDATA section. - bool CDATA() const { return cdata; } - /// Turns on or off a CDATA representation of text. - void SetCDATA( bool _cdata ) { cdata = _cdata; } - - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - - virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; + /** Constructor for text element. By default, it is treated as + normal, encoded text. If you want it be output as a CDATA text + element, set the parameter _cdata to 'true' + */ + TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + virtual ~TiXmlText() {} + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TINYXML_TEXT) + { + SetValue( initValue ); + cdata = false; + } + #endif + + TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TINYXML_TEXT ) { copy.CopyTo( this ); } + void operator=( const TiXmlText& base ) { base.CopyTo( this ); } + + // Write this text object to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; + + /// Queries whether this represents text using a CDATA section. + bool CDATA() const { return cdata; } + /// Turns on or off a CDATA representation of text. + void SetCDATA( bool _cdata ) { cdata = _cdata; } + + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + + virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; protected : - /// [internal use] Creates a new Element and returns it. - virtual TiXmlNode* Clone() const; - void CopyTo( TiXmlText* target ) const; + /// [internal use] Creates a new Element and returns it. + virtual TiXmlNode* Clone() const; + void CopyTo( TiXmlText* target ) const; - bool Blank() const; // returns true if all white space and new lines - // [internal use] - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif + bool Blank() const; // returns true if all white space and new lines + // [internal use] + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif private: - bool cdata; // true if this should be input and output as a CDATA style text element + bool cdata; // true if this should be input and output as a CDATA style text element }; /** In correct XML the declaration is the first entry in the file. - @verbatim - - @endverbatim + @verbatim + + @endverbatim - TinyXml will happily read or write files without a declaration, - however. There are 3 possible attributes to the declaration: - version, encoding, and standalone. + TinyXml will happily read or write files without a declaration, + however. There are 3 possible attributes to the declaration: + version, encoding, and standalone. - Note: In this version of the code, the attributes are - handled as special cases, not generic attributes, simply - because there can only be at most 3 and they are always the same. + Note: In this version of the code, the attributes are + handled as special cases, not generic attributes, simply + because there can only be at most 3 and they are always the same. */ class TiXmlDeclaration : public TiXmlNode { public: - /// Construct an empty declaration. - TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} + /// Construct an empty declaration. + TiXmlDeclaration() : TiXmlNode( TiXmlNode::TINYXML_DECLARATION ) {} #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDeclaration( const std::string& _version, - const std::string& _encoding, - const std::string& _standalone ); + /// Constructor. + TiXmlDeclaration( const std::string& _version, + const std::string& _encoding, + const std::string& _standalone ); #endif - /// Construct. - TiXmlDeclaration( const char* _version, - const char* _encoding, - const char* _standalone ); + /// Construct. + TiXmlDeclaration( const char* _version, + const char* _encoding, + const char* _standalone ); - TiXmlDeclaration( const TiXmlDeclaration& copy ); - void operator=( const TiXmlDeclaration& copy ); + TiXmlDeclaration( const TiXmlDeclaration& copy ); + void operator=( const TiXmlDeclaration& copy ); - virtual ~TiXmlDeclaration() {} + virtual ~TiXmlDeclaration() {} - /// Version. Will return an empty string if none was found. - const char *Version() const { return version.c_str (); } - /// Encoding. Will return an empty string if none was found. - const char *Encoding() const { return encoding.c_str (); } - /// Is this a standalone document? - const char *Standalone() const { return standalone.c_str (); } + /// Version. Will return an empty string if none was found. + const char *Version() const { return version.c_str (); } + /// Encoding. Will return an empty string if none was found. + const char *Encoding() const { return encoding.c_str (); } + /// Is this a standalone document? + const char *Standalone() const { return standalone.c_str (); } - /// Creates a copy of this Declaration and returns it. - virtual TiXmlNode* Clone() const; - // Print this declaration to a FILE stream. - virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; - virtual void Print( FILE* cfile, int depth ) const { - Print( cfile, depth, 0 ); - } + /// Creates a copy of this Declaration and returns it. + virtual TiXmlNode* Clone() const; + // Print this declaration to a FILE stream. + virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; + virtual void Print( FILE* cfile, int depth ) const { + Print( cfile, depth, 0 ); + } - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* visitor ) const; + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* visitor ) const; protected: - void CopyTo( TiXmlDeclaration* target ) const; - // used to be public - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif + void CopyTo( TiXmlDeclaration* target ) const; + // used to be public + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif private: - TIXML_STRING version; - TIXML_STRING encoding; - TIXML_STRING standalone; + TIXML_STRING version; + TIXML_STRING encoding; + TIXML_STRING standalone; }; /** Any tag that tinyXml doesn't recognize is saved as an - unknown. It is a tag of text, but should not be modified. - It will be written back to the XML, unchanged, when the file - is saved. + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. - DTD tags get thrown into TiXmlUnknowns. + DTD tags get thrown into TiXmlUnknowns. */ class TiXmlUnknown : public TiXmlNode { public: - TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} - virtual ~TiXmlUnknown() {} + TiXmlUnknown() : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) {} + virtual ~TiXmlUnknown() {} - TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } - void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } + TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::TINYXML_UNKNOWN ) { copy.CopyTo( this ); } + void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } - /// Creates a copy of this Unknown and returns it. - virtual TiXmlNode* Clone() const; - // Print this Unknown to a FILE stream. - virtual void Print( FILE* cfile, int depth ) const; + /// Creates a copy of this Unknown and returns it. + virtual TiXmlNode* Clone() const; + // Print this Unknown to a FILE stream. + virtual void Print( FILE* cfile, int depth ) const; - virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); + virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); - virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; protected: - void CopyTo( TiXmlUnknown* target ) const; + void CopyTo( TiXmlUnknown* target ) const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif private: }; /** Always the top level node. A document binds together all the - XML pieces. It can be saved, loaded, and printed to the screen. - The 'value' of a document node is the xml file name. + XML pieces. It can be saved, loaded, and printed to the screen. + The 'value' of a document node is the xml file name. */ class TiXmlDocument : public TiXmlNode { public: - /// Create an empty document, that has no name. - TiXmlDocument(); - /// Create a document with a name. The name of the document is also the filename of the xml. - TiXmlDocument( const char * documentName ); - - #ifdef TIXML_USE_STL - /// Constructor. - TiXmlDocument( const std::string& documentName ); - #endif - - TiXmlDocument( const TiXmlDocument& copy ); - void operator=( const TiXmlDocument& copy ); - - virtual ~TiXmlDocument() {} - - /** Load a file using the current document value. - Returns true if successful. Will delete any existing - document data before loading. - */ - bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the current document value. Returns true if successful. - bool SaveFile() const; - /// Load a file using the given filename. Returns true if successful. - bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given filename. Returns true if successful. - bool SaveFile( const char * filename ) const; - /** Load a file using the given FILE*. Returns true if successful. Note that this method - doesn't stream - the entire object pointed at by the FILE* - will be interpreted as an XML file. TinyXML doesn't stream in XML from the current - file location. Streaming may be added in the future. - */ - bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - /// Save a file using the given FILE*. Returns true if successful. - bool SaveFile( FILE* ) const; - - #ifdef TIXML_USE_STL - bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. - { - return LoadFile( filename.c_str(), encoding ); - } - bool SaveFile( const std::string& filename ) const ///< STL std::string version. - { - return SaveFile( filename.c_str() ); - } - #endif - - /** Parse the given null terminated block of xml data. Passing in an encoding to this - method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml - to use that encoding, regardless of what TinyXml might otherwise try to detect. - */ - virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); - - /** Get the root element -- the only top level element -- of the document. - In well formed XML, there should only be one. TinyXml is tolerant of - multiple elements at the document level. - */ - const TiXmlElement* RootElement() const { return FirstChildElement(); } - TiXmlElement* RootElement() { return FirstChildElement(); } - - /** If an error occurs, Error will be set to true. Also, - - The ErrorId() will contain the integer identifier of the error (not generally useful) - - The ErrorDesc() method will return the name of the error. (very useful) - - The ErrorRow() and ErrorCol() will return the location of the error (if known) - */ - bool Error() const { return error; } - - /// Contains a textual (english) description of the error if one occurs. - const char * ErrorDesc() const { return errorDesc.c_str (); } - - /** Generally, you probably want the error string ( ErrorDesc() ). But if you - prefer the ErrorId, this function will fetch it. - */ - int ErrorId() const { return errorId; } - - /** Returns the location (if known) of the error. The first column is column 1, - and the first row is row 1. A value of 0 means the row and column wasn't applicable - (memory errors, for example, have no row/column) or the parser lost the error. (An - error in the error reporting, in that case.) - - @sa SetTabSize, Row, Column - */ - int ErrorRow() const { return errorLocation.row+1; } - int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() - - /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) - to report the correct values for row and column. It does not change the output - or input in any way. - - By calling this method, with a tab size - greater than 0, the row and column of each node and attribute is stored - when the file is loaded. Very useful for tracking the DOM back in to - the source file. - - The tab size is required for calculating the location of nodes. If not - set, the default of 4 is used. The tabsize is set per document. Setting - the tabsize to 0 disables row/column tracking. - - Note that row and column tracking is not supported when using operator>>. - - The tab size needs to be enabled before the parse or load. Correct usage: - @verbatim - TiXmlDocument doc; - doc.SetTabSize( 8 ); - doc.Load( "myfile.xml" ); - @endverbatim - - @sa Row, Column - */ - void SetTabSize( int _tabsize ) { tabsize = _tabsize; } - - int TabSize() const { return tabsize; } - - /** If you have handled the error, it can be reset with this call. The error - state is automatically cleared if you Parse a new XML block. - */ - void ClearError() { error = false; - errorId = 0; - errorDesc = ""; - errorLocation.row = errorLocation.col = 0; - //errorLocation.last = 0; - } - - /** Write the document to standard out using formatted printing ("pretty print"). */ - void Print() const { Print( stdout, 0 ); } - - /* Write the document to a string using formatted printing ("pretty print"). This - will allocate a character array (new char[]) and return it as a pointer. The - calling code pust call delete[] on the return char* to avoid a memory leak. - */ - //char* PrintToMemory() const; - - /// Print this Document to a FILE stream. - virtual void Print( FILE* cfile, int depth = 0 ) const; - // [internal use] - void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); - - virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. - - /** Walk the XML tree visiting this node and all of its children. - */ - virtual bool Accept( TiXmlVisitor* content ) const; + /// Create an empty document, that has no name. + TiXmlDocument(); + /// Create a document with a name. The name of the document is also the filename of the xml. + TiXmlDocument( const char * documentName ); + + #ifdef TIXML_USE_STL + /// Constructor. + TiXmlDocument( const std::string& documentName ); + #endif + + TiXmlDocument( const TiXmlDocument& copy ); + void operator=( const TiXmlDocument& copy ); + + virtual ~TiXmlDocument() {} + + /** Load a file using the current document value. + Returns true if successful. Will delete any existing + document data before loading. + */ + bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the current document value. Returns true if successful. + bool SaveFile() const; + /// Load a file using the given filename. Returns true if successful. + bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given filename. Returns true if successful. + bool SaveFile( const char * filename ) const; + /** Load a file using the given FILE*. Returns true if successful. Note that this method + doesn't stream - the entire object pointed at by the FILE* + will be interpreted as an XML file. TinyXML doesn't stream in XML from the current + file location. Streaming may be added in the future. + */ + bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + /// Save a file using the given FILE*. Returns true if successful. + bool SaveFile( FILE* ) const; + + #ifdef TIXML_USE_STL + bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. + { + return LoadFile( filename.c_str(), encoding ); + } + bool SaveFile( const std::string& filename ) const ///< STL std::string version. + { + return SaveFile( filename.c_str() ); + } + #endif + + /** Parse the given null terminated block of xml data. Passing in an encoding to this + method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml + to use that encoding, regardless of what TinyXml might otherwise try to detect. + */ + virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); + + /** Get the root element -- the only top level element -- of the document. + In well formed XML, there should only be one. TinyXml is tolerant of + multiple elements at the document level. + */ + const TiXmlElement* RootElement() const { return FirstChildElement(); } + TiXmlElement* RootElement() { return FirstChildElement(); } + + /** If an error occurs, Error will be set to true. Also, + - The ErrorId() will contain the integer identifier of the error (not generally useful) + - The ErrorDesc() method will return the name of the error. (very useful) + - The ErrorRow() and ErrorCol() will return the location of the error (if known) + */ + bool Error() const { return error; } + + /// Contains a textual (english) description of the error if one occurs. + const char * ErrorDesc() const { return errorDesc.c_str (); } + + /** Generally, you probably want the error string ( ErrorDesc() ). But if you + prefer the ErrorId, this function will fetch it. + */ + int ErrorId() const { return errorId; } + + /** Returns the location (if known) of the error. The first column is column 1, + and the first row is row 1. A value of 0 means the row and column wasn't applicable + (memory errors, for example, have no row/column) or the parser lost the error. (An + error in the error reporting, in that case.) + + @sa SetTabSize, Row, Column + */ + int ErrorRow() const { return errorLocation.row+1; } + int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() + + /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) + to report the correct values for row and column. It does not change the output + or input in any way. + + By calling this method, with a tab size + greater than 0, the row and column of each node and attribute is stored + when the file is loaded. Very useful for tracking the DOM back in to + the source file. + + The tab size is required for calculating the location of nodes. If not + set, the default of 4 is used. The tabsize is set per document. Setting + the tabsize to 0 disables row/column tracking. + + Note that row and column tracking is not supported when using operator>>. + + The tab size needs to be enabled before the parse or load. Correct usage: + @verbatim + TiXmlDocument doc; + doc.SetTabSize( 8 ); + doc.Load( "myfile.xml" ); + @endverbatim + + @sa Row, Column + */ + void SetTabSize( int _tabsize ) { tabsize = _tabsize; } + + int TabSize() const { return tabsize; } + + /** If you have handled the error, it can be reset with this call. The error + state is automatically cleared if you Parse a new XML block. + */ + void ClearError() { error = false; + errorId = 0; + errorDesc = ""; + errorLocation.row = errorLocation.col = 0; + //errorLocation.last = 0; + } + + /** Write the document to standard out using formatted printing ("pretty print"). */ + void Print() const { Print( stdout, 0 ); } + + /* Write the document to a string using formatted printing ("pretty print"). This + will allocate a character array (new char[]) and return it as a pointer. The + calling code pust call delete[] on the return char* to avoid a memory leak. + */ + //char* PrintToMemory() const; + + /// Print this Document to a FILE stream. + virtual void Print( FILE* cfile, int depth = 0 ) const; + // [internal use] + void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); + + virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. + + /** Walk the XML tree visiting this node and all of its children. + */ + virtual bool Accept( TiXmlVisitor* content ) const; protected : - // [internal use] - virtual TiXmlNode* Clone() const; - #ifdef TIXML_USE_STL - virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); - #endif + // [internal use] + virtual TiXmlNode* Clone() const; + #ifdef TIXML_USE_STL + virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); + #endif private: - void CopyTo( TiXmlDocument* target ) const; - - bool error; - int errorId; - TIXML_STRING errorDesc; - int tabsize; - TiXmlCursor errorLocation; - bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. + void CopyTo( TiXmlDocument* target ) const; + + bool error; + int errorId; + TIXML_STRING errorDesc; + int tabsize; + TiXmlCursor errorLocation; + bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. }; /** - A TiXmlHandle is a class that wraps a node pointer with null checks; this is - an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml - DOM structure. It is a separate utility class. - - Take an example: - @verbatim - - - - - - - @endverbatim - - Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very - easy to write a *lot* of code that looks like: - - @verbatim - TiXmlElement* root = document.FirstChildElement( "Document" ); - if ( root ) - { - TiXmlElement* element = root->FirstChildElement( "Element" ); - if ( element ) - { - TiXmlElement* child = element->FirstChildElement( "Child" ); - if ( child ) - { - TiXmlElement* child2 = child->NextSiblingElement( "Child" ); - if ( child2 ) - { - // Finally do something useful. - @endverbatim - - And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity - of such code. A TiXmlHandle checks for null pointers so it is perfectly safe - and correct to use: - - @verbatim - TiXmlHandle docHandle( &document ); - TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); - if ( child2 ) - { - // do something useful - @endverbatim - - Which is MUCH more concise and useful. - - It is also safe to copy handles - internally they are nothing more than node pointers. - @verbatim - TiXmlHandle handleCopy = handle; - @endverbatim - - What they should not be used for is iteration: - - @verbatim - int i=0; - while ( true ) - { - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); - if ( !child ) - break; - // do something - ++i; - } - @endverbatim - - It seems reasonable, but it is in fact two embedded while loops. The Child method is - a linear walk to find the element, so this code would iterate much more than it needs - to. Instead, prefer: - - @verbatim - TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); - - for( child; child; child=child->NextSiblingElement() ) - { - // do something - } - @endverbatim + A TiXmlHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + TiXmlElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + TiXmlElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + TiXmlElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + TiXmlElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity + of such code. A TiXmlHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + TiXmlHandle docHandle( &document ); + TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + TiXmlHandle handleCopy = handle; + @endverbatim + + What they should not be used for is iteration: + + @verbatim + int i=0; + while ( true ) + { + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); + if ( !child ) + break; + // do something + ++i; + } + @endverbatim + + It seems reasonable, but it is in fact two embedded while loops. The Child method is + a linear walk to find the element, so this code would iterate much more than it needs + to. Instead, prefer: + + @verbatim + TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); + + for( child; child; child=child->NextSiblingElement() ) + { + // do something + } + @endverbatim */ class TiXmlHandle { public: - /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. - TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } - /// Copy constructor - TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } - TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } - - /// Return a handle to the first child node. - TiXmlHandle FirstChild() const; - /// Return a handle to the first child node with the given name. - TiXmlHandle FirstChild( const char * value ) const; - /// Return a handle to the first child element. - TiXmlHandle FirstChildElement() const; - /// Return a handle to the first child element with the given name. - TiXmlHandle FirstChildElement( const char * value ) const; - - /** Return a handle to the "index" child with the given name. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( const char* value, int index ) const; - /** Return a handle to the "index" child. - The first child is 0, the second 1, etc. - */ - TiXmlHandle Child( int index ) const; - /** Return a handle to the "index" child element with the given name. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( const char* value, int index ) const; - /** Return a handle to the "index" child element. - The first child element is 0, the second 1, etc. Note that only TiXmlElements - are indexed: other types are not counted. - */ - TiXmlHandle ChildElement( int index ) const; - - #ifdef TIXML_USE_STL - TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } - TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } - - TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } - TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } - #endif - - /** Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* ToNode() const { return node; } - /** Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } - /** Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } - /** Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } - - /** @deprecated use ToNode. - Return the handle as a TiXmlNode. This may return null. - */ - TiXmlNode* Node() const { return ToNode(); } - /** @deprecated use ToElement. - Return the handle as a TiXmlElement. This may return null. - */ - TiXmlElement* Element() const { return ToElement(); } - /** @deprecated use ToText() - Return the handle as a TiXmlText. This may return null. - */ - TiXmlText* Text() const { return ToText(); } - /** @deprecated use ToUnknown() - Return the handle as a TiXmlUnknown. This may return null. - */ - TiXmlUnknown* Unknown() const { return ToUnknown(); } + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } + /// Copy constructor + TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } + TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } + + /// Return a handle to the first child node. + TiXmlHandle FirstChild() const; + /// Return a handle to the first child node with the given name. + TiXmlHandle FirstChild( const char * value ) const; + /// Return a handle to the first child element. + TiXmlHandle FirstChildElement() const; + /// Return a handle to the first child element with the given name. + TiXmlHandle FirstChildElement( const char * value ) const; + + /** Return a handle to the "index" child with the given name. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( const char* value, int index ) const; + /** Return a handle to the "index" child. + The first child is 0, the second 1, etc. + */ + TiXmlHandle Child( int index ) const; + /** Return a handle to the "index" child element with the given name. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( const char* value, int index ) const; + /** Return a handle to the "index" child element. + The first child element is 0, the second 1, etc. Note that only TiXmlElements + are indexed: other types are not counted. + */ + TiXmlHandle ChildElement( int index ) const; + + #ifdef TIXML_USE_STL + TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } + TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } + + TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } + TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } + #endif + + /** Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* ToNode() const { return node; } + /** Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } + /** Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } + /** Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } + + /** @deprecated use ToNode. + Return the handle as a TiXmlNode. This may return null. + */ + TiXmlNode* Node() const { return ToNode(); } + /** @deprecated use ToElement. + Return the handle as a TiXmlElement. This may return null. + */ + TiXmlElement* Element() const { return ToElement(); } + /** @deprecated use ToText() + Return the handle as a TiXmlText. This may return null. + */ + TiXmlText* Text() const { return ToText(); } + /** @deprecated use ToUnknown() + Return the handle as a TiXmlUnknown. This may return null. + */ + TiXmlUnknown* Unknown() const { return ToUnknown(); } private: - TiXmlNode* node; + TiXmlNode* node; }; /** Print to memory functionality. The TiXmlPrinter is useful when you need to: - -# Print to memory (especially in non-STL mode) - -# Control formatting (line endings, etc.) + -# Print to memory (especially in non-STL mode) + -# Control formatting (line endings, etc.) - When constructed, the TiXmlPrinter is in its default "pretty printing" mode. - Before calling Accept() you can call methods to control the printing - of the XML document. After TiXmlNode::Accept() is called, the printed document can - be accessed via the CStr(), Str(), and Size() methods. + When constructed, the TiXmlPrinter is in its default "pretty printing" mode. + Before calling Accept() you can call methods to control the printing + of the XML document. After TiXmlNode::Accept() is called, the printed document can + be accessed via the CStr(), Str(), and Size() methods. - TiXmlPrinter uses the Visitor API. - @verbatim - TiXmlPrinter printer; - printer.SetIndent( "\t" ); + TiXmlPrinter uses the Visitor API. + @verbatim + TiXmlPrinter printer; + printer.SetIndent( "\t" ); - doc.Accept( &printer ); - fprintf( stdout, "%s", printer.CStr() ); - @endverbatim + doc.Accept( &printer ); + fprintf( stdout, "%s", printer.CStr() ); + @endverbatim */ class TiXmlPrinter : public TiXmlVisitor { public: - TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), - buffer(), indent( " " ), lineBreak( "\n" ) {} - - virtual bool VisitEnter( const TiXmlDocument& doc ); - virtual bool VisitExit( const TiXmlDocument& doc ); - - virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); - virtual bool VisitExit( const TiXmlElement& element ); - - virtual bool Visit( const TiXmlDeclaration& declaration ); - virtual bool Visit( const TiXmlText& text ); - virtual bool Visit( const TiXmlComment& comment ); - virtual bool Visit( const TiXmlUnknown& unknown ); - - /** Set the indent characters for printing. By default 4 spaces - but tab (\t) is also useful, or null/empty string for no indentation. - */ - void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } - /// Query the indention string. - const char* Indent() { return indent.c_str(); } - /** Set the line breaking string. By default set to newline (\n). - Some operating systems prefer other characters, or can be - set to the null/empty string for no indenation. - */ - void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } - /// Query the current line breaking string. - const char* LineBreak() { return lineBreak.c_str(); } - - /** Switch over to "stream printing" which is the most dense formatting without - linebreaks. Common when the XML is needed for network transmission. - */ - void SetStreamPrinting() { indent = ""; - lineBreak = ""; - } - /// Return the result. - const char* CStr() { return buffer.c_str(); } - /// Return the length of the result string. - size_t Size() { return buffer.size(); } - - #ifdef TIXML_USE_STL - /// Return the result. - const std::string& Str() { return buffer; } - #endif + TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), + buffer(), indent( " " ), lineBreak( "\n" ) {} + + virtual bool VisitEnter( const TiXmlDocument& doc ); + virtual bool VisitExit( const TiXmlDocument& doc ); + + virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); + virtual bool VisitExit( const TiXmlElement& element ); + + virtual bool Visit( const TiXmlDeclaration& declaration ); + virtual bool Visit( const TiXmlText& text ); + virtual bool Visit( const TiXmlComment& comment ); + virtual bool Visit( const TiXmlUnknown& unknown ); + + /** Set the indent characters for printing. By default 4 spaces + but tab (\t) is also useful, or null/empty string for no indentation. + */ + void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } + /// Query the indention string. + const char* Indent() { return indent.c_str(); } + /** Set the line breaking string. By default set to newline (\n). + Some operating systems prefer other characters, or can be + set to the null/empty string for no indenation. + */ + void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } + /// Query the current line breaking string. + const char* LineBreak() { return lineBreak.c_str(); } + + /** Switch over to "stream printing" which is the most dense formatting without + linebreaks. Common when the XML is needed for network transmission. + */ + void SetStreamPrinting() { indent = ""; + lineBreak = ""; + } + /// Return the result. + const char* CStr() { return buffer.c_str(); } + /// Return the length of the result string. + size_t Size() { return buffer.size(); } + + #ifdef TIXML_USE_STL + /// Return the result. + const std::string& Str() { return buffer; } + #endif private: - void DoIndent() { - for( int i=0; i